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     const bool include_aliases = true;
489     if (CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact(
490             cmd_obj.GetCommandName(), include_aliases)) {
491       if (m_interpreter.AliasExists(alias_command) ||
492           m_interpreter.UserCommandExists(alias_command)) {
493         result.AppendWarningWithFormat(
494             "Overwriting existing definition for '%s'.\n",
495             alias_command.str().c_str());
496       }
497       if (CommandAlias *alias = m_interpreter.AddAlias(
498               alias_command, cmd_obj_sp, raw_command_string)) {
499         if (m_command_options.m_help.OptionWasSet())
500           alias->SetHelp(m_command_options.m_help.GetCurrentValue());
501         if (m_command_options.m_long_help.OptionWasSet())
502           alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
503         result.SetStatus(eReturnStatusSuccessFinishNoResult);
504       } else {
505         result.AppendError("Unable to create requested alias.\n");
506       }
507 
508     } else {
509       result.AppendError("Unable to create requested alias.\n");
510     }
511 
512     return result.Succeeded();
513   }
514 
515   bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
516     size_t argc = args.GetArgumentCount();
517 
518     if (argc < 2) {
519       result.AppendError("'command alias' requires at least two arguments");
520       return false;
521     }
522 
523     // Save these in std::strings since we're going to shift them off.
524     const std::string alias_command(std::string(args[0].ref()));
525     const std::string actual_command(std::string(args[1].ref()));
526 
527     args.Shift(); // Shift the alias command word off the argument vector.
528     args.Shift(); // Shift the old command word off the argument vector.
529 
530     // Verify that the command is alias'able, and get the appropriate command
531     // object.
532 
533     if (m_interpreter.CommandExists(alias_command)) {
534       result.AppendErrorWithFormat(
535           "'%s' is a permanent debugger command and cannot be redefined.\n",
536           alias_command.c_str());
537       return false;
538     }
539 
540     if (m_interpreter.UserMultiwordCommandExists(alias_command)) {
541       result.AppendErrorWithFormat(
542           "'%s' is user container command and cannot be overwritten.\n"
543           "Delete it first with 'command container delete'",
544           alias_command.c_str());
545       return false;
546     }
547 
548     CommandObjectSP command_obj_sp(
549         m_interpreter.GetCommandSPExact(actual_command, true));
550     CommandObjectSP subcommand_obj_sp;
551     bool use_subcommand = false;
552     if (!command_obj_sp) {
553       result.AppendErrorWithFormat("'%s' is not an existing command.\n",
554                                    actual_command.c_str());
555       return false;
556     }
557     CommandObject *cmd_obj = command_obj_sp.get();
558     CommandObject *sub_cmd_obj = nullptr;
559     OptionArgVectorSP option_arg_vector_sp =
560         OptionArgVectorSP(new OptionArgVector);
561 
562     while (cmd_obj->IsMultiwordObject() && !args.empty()) {
563       auto sub_command = args[0].ref();
564       assert(!sub_command.empty());
565       subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command);
566       if (!subcommand_obj_sp) {
567         result.AppendErrorWithFormat(
568             "'%s' is not a valid sub-command of '%s'.  "
569             "Unable to create alias.\n",
570             args[0].c_str(), actual_command.c_str());
571         return false;
572       }
573 
574       sub_cmd_obj = subcommand_obj_sp.get();
575       use_subcommand = true;
576       args.Shift(); // Shift the sub_command word off the argument vector.
577       cmd_obj = sub_cmd_obj;
578     }
579 
580     // Verify & handle any options/arguments passed to the alias command
581 
582     std::string args_string;
583 
584     if (!args.empty()) {
585       CommandObjectSP tmp_sp =
586           m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName());
587       if (use_subcommand)
588         tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName());
589 
590       args.GetCommandString(args_string);
591     }
592 
593     if (m_interpreter.AliasExists(alias_command) ||
594         m_interpreter.UserCommandExists(alias_command)) {
595       result.AppendWarningWithFormat(
596           "Overwriting existing definition for '%s'.\n", alias_command.c_str());
597     }
598 
599     if (CommandAlias *alias = m_interpreter.AddAlias(
600             alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp,
601             args_string)) {
602       if (m_command_options.m_help.OptionWasSet())
603         alias->SetHelp(m_command_options.m_help.GetCurrentValue());
604       if (m_command_options.m_long_help.OptionWasSet())
605         alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
606       result.SetStatus(eReturnStatusSuccessFinishNoResult);
607     } else {
608       result.AppendError("Unable to create requested alias.\n");
609       return false;
610     }
611 
612     return result.Succeeded();
613   }
614 };
615 
616 #pragma mark CommandObjectCommandsUnalias
617 // CommandObjectCommandsUnalias
618 
619 class CommandObjectCommandsUnalias : public CommandObjectParsed {
620 public:
621   CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
622       : CommandObjectParsed(
623             interpreter, "command unalias",
624             "Delete one or more custom commands defined by 'command alias'.",
625             nullptr) {
626     CommandArgumentEntry arg;
627     CommandArgumentData alias_arg;
628 
629     // Define the first (and only) variant of this arg.
630     alias_arg.arg_type = eArgTypeAliasName;
631     alias_arg.arg_repetition = eArgRepeatPlain;
632 
633     // There is only one variant this argument could be; put it into the
634     // argument entry.
635     arg.push_back(alias_arg);
636 
637     // Push the data for the first argument into the m_arguments vector.
638     m_arguments.push_back(arg);
639   }
640 
641   ~CommandObjectCommandsUnalias() override = default;
642 
643   void
644   HandleArgumentCompletion(CompletionRequest &request,
645                            OptionElementVector &opt_element_vector) override {
646     if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
647       return;
648 
649     for (const auto &ent : m_interpreter.GetAliases()) {
650       request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp());
651     }
652   }
653 
654 protected:
655   bool DoExecute(Args &args, CommandReturnObject &result) override {
656     CommandObject::CommandMap::iterator pos;
657     CommandObject *cmd_obj;
658 
659     if (args.empty()) {
660       result.AppendError("must call 'unalias' with a valid alias");
661       return false;
662     }
663 
664     auto command_name = args[0].ref();
665     cmd_obj = m_interpreter.GetCommandObject(command_name);
666     if (!cmd_obj) {
667       result.AppendErrorWithFormat(
668           "'%s' is not a known command.\nTry 'help' to see a "
669           "current list of commands.\n",
670           args[0].c_str());
671       return false;
672     }
673 
674     if (m_interpreter.CommandExists(command_name)) {
675       if (cmd_obj->IsRemovable()) {
676         result.AppendErrorWithFormat(
677             "'%s' is not an alias, it is a debugger command which can be "
678             "removed using the 'command delete' command.\n",
679             args[0].c_str());
680       } else {
681         result.AppendErrorWithFormat(
682             "'%s' is a permanent debugger command and cannot be removed.\n",
683             args[0].c_str());
684       }
685       return false;
686     }
687 
688     if (!m_interpreter.RemoveAlias(command_name)) {
689       if (m_interpreter.AliasExists(command_name))
690         result.AppendErrorWithFormat(
691             "Error occurred while attempting to unalias '%s'.\n",
692             args[0].c_str());
693       else
694         result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
695                                      args[0].c_str());
696       return false;
697     }
698 
699     result.SetStatus(eReturnStatusSuccessFinishNoResult);
700     return result.Succeeded();
701   }
702 };
703 
704 #pragma mark CommandObjectCommandsDelete
705 // CommandObjectCommandsDelete
706 
707 class CommandObjectCommandsDelete : public CommandObjectParsed {
708 public:
709   CommandObjectCommandsDelete(CommandInterpreter &interpreter)
710       : CommandObjectParsed(
711             interpreter, "command delete",
712             "Delete one or more custom commands defined by 'command regex'.",
713             nullptr) {
714     CommandArgumentEntry arg;
715     CommandArgumentData alias_arg;
716 
717     // Define the first (and only) variant of this arg.
718     alias_arg.arg_type = eArgTypeCommandName;
719     alias_arg.arg_repetition = eArgRepeatPlain;
720 
721     // There is only one variant this argument could be; put it into the
722     // argument entry.
723     arg.push_back(alias_arg);
724 
725     // Push the data for the first argument into the m_arguments vector.
726     m_arguments.push_back(arg);
727   }
728 
729   ~CommandObjectCommandsDelete() override = default;
730 
731   void
732   HandleArgumentCompletion(CompletionRequest &request,
733                            OptionElementVector &opt_element_vector) override {
734     if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
735       return;
736 
737     for (const auto &ent : m_interpreter.GetCommands()) {
738       if (ent.second->IsRemovable())
739         request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp());
740     }
741   }
742 
743 protected:
744   bool DoExecute(Args &args, CommandReturnObject &result) override {
745     CommandObject::CommandMap::iterator pos;
746 
747     if (args.empty()) {
748       result.AppendErrorWithFormat("must call '%s' with one or more valid user "
749                                    "defined regular expression command names",
750                                    GetCommandName().str().c_str());
751       return false;
752     }
753 
754     auto command_name = args[0].ref();
755     if (!m_interpreter.CommandExists(command_name)) {
756       StreamString error_msg_stream;
757       const bool generate_upropos = true;
758       const bool generate_type_lookup = false;
759       CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
760           &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(),
761           generate_upropos, generate_type_lookup);
762       result.AppendError(error_msg_stream.GetString());
763       return false;
764     }
765 
766     if (!m_interpreter.RemoveCommand(command_name)) {
767       result.AppendErrorWithFormat(
768           "'%s' is a permanent debugger command and cannot be removed.\n",
769           args[0].c_str());
770       return false;
771     }
772 
773     result.SetStatus(eReturnStatusSuccessFinishNoResult);
774     return true;
775   }
776 };
777 
778 // CommandObjectCommandsAddRegex
779 
780 #define LLDB_OPTIONS_regex
781 #include "CommandOptions.inc"
782 
783 #pragma mark CommandObjectCommandsAddRegex
784 
785 class CommandObjectCommandsAddRegex : public CommandObjectParsed,
786                                       public IOHandlerDelegateMultiline {
787 public:
788   CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
789       : CommandObjectParsed(
790             interpreter, "command regex",
791             "Define a custom command in terms of "
792             "existing commands by matching "
793             "regular expressions.",
794             "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
795         IOHandlerDelegateMultiline("",
796                                    IOHandlerDelegate::Completion::LLDBCommand),
797         m_options() {
798     SetHelpLong(
799         R"(
800 )"
801         "This command allows the user to create powerful regular expression commands \
802 with substitutions. The regular expressions and substitutions are specified \
803 using the regular expression substitution format of:"
804         R"(
805 
806     s/<regex>/<subst>/
807 
808 )"
809         "<regex> is a regular expression that can use parenthesis to capture regular \
810 expression input and substitute the captured matches in the output using %1 \
811 for the first match, %2 for the second, and so on."
812         R"(
813 
814 )"
815         "The regular expressions can all be specified on the command line if more than \
816 one argument is provided. If just the command name is provided on the command \
817 line, then the regular expressions and substitutions can be entered on separate \
818 lines, followed by an empty line to terminate the command definition."
819         R"(
820 
821 EXAMPLES
822 
823 )"
824         "The following example will define a regular expression command named 'f' that \
825 will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
826 a number follows 'f':"
827         R"(
828 
829     (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
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() : Options() {}
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), m_fetched_help_long(false) {
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;
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         m_options() {
1244     CommandArgumentEntry arg1;
1245     CommandArgumentData cmd_arg;
1246 
1247     // Define the first (and only) variant of this arg.
1248     cmd_arg.arg_type = eArgTypeFilename;
1249     cmd_arg.arg_repetition = eArgRepeatPlus;
1250 
1251     // There is only one variant this argument could be; put it into the
1252     // argument entry.
1253     arg1.push_back(cmd_arg);
1254 
1255     // Push the data for the first argument into the m_arguments vector.
1256     m_arguments.push_back(arg1);
1257   }
1258 
1259   ~CommandObjectCommandsScriptImport() override = default;
1260 
1261   void
1262   HandleArgumentCompletion(CompletionRequest &request,
1263                            OptionElementVector &opt_element_vector) override {
1264     CommandCompletions::InvokeCommonCompletionCallbacks(
1265         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
1266         request, nullptr);
1267   }
1268 
1269   Options *GetOptions() override { return &m_options; }
1270 
1271 protected:
1272   class CommandOptions : public Options {
1273   public:
1274     CommandOptions() : Options() {}
1275 
1276     ~CommandOptions() override = default;
1277 
1278     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1279                           ExecutionContext *execution_context) override {
1280       Status error;
1281       const int short_option = m_getopt_table[option_idx].val;
1282 
1283       switch (short_option) {
1284       case 'r':
1285         // NO-OP
1286         break;
1287       case 'c':
1288         relative_to_command_file = true;
1289         break;
1290       case 's':
1291         silent = true;
1292         break;
1293       default:
1294         llvm_unreachable("Unimplemented option");
1295       }
1296 
1297       return error;
1298     }
1299 
1300     void OptionParsingStarting(ExecutionContext *execution_context) override {
1301       relative_to_command_file = false;
1302     }
1303 
1304     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1305       return llvm::makeArrayRef(g_script_import_options);
1306     }
1307     bool relative_to_command_file = false;
1308     bool silent = false;
1309   };
1310 
1311   bool DoExecute(Args &command, CommandReturnObject &result) override {
1312     if (command.empty()) {
1313       result.AppendError("command script import needs one or more arguments");
1314       return false;
1315     }
1316 
1317     FileSpec source_dir = {};
1318     if (m_options.relative_to_command_file) {
1319       source_dir = GetDebugger().GetCommandInterpreter().GetCurrentSourceDir();
1320       if (!source_dir) {
1321         result.AppendError("command script import -c can only be specified "
1322                            "from a command file");
1323         return false;
1324       }
1325     }
1326 
1327     for (auto &entry : command.entries()) {
1328       Status error;
1329 
1330       LoadScriptOptions options;
1331       options.SetInitSession(true);
1332       options.SetSilent(m_options.silent);
1333 
1334       // FIXME: this is necessary because CommandObject::CheckRequirements()
1335       // assumes that commands won't ever be recursively invoked, but it's
1336       // actually possible to craft a Python script that does other "command
1337       // script imports" in __lldb_init_module the real fix is to have
1338       // recursive commands possible with a CommandInvocation object separate
1339       // from the CommandObject itself, so that recursive command invocations
1340       // won't stomp on each other (wrt to execution contents, options, and
1341       // more)
1342       m_exe_ctx.Clear();
1343       if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule(
1344               entry.c_str(), options, error, /*module_sp=*/nullptr,
1345               source_dir)) {
1346         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1347       } else {
1348         result.AppendErrorWithFormat("module importing failed: %s",
1349                                      error.AsCString());
1350       }
1351     }
1352 
1353     return result.Succeeded();
1354   }
1355 
1356   CommandOptions m_options;
1357 };
1358 
1359 // CommandObjectCommandsScriptAdd
1360 static constexpr OptionEnumValueElement g_script_synchro_type[] = {
1361     {
1362         eScriptedCommandSynchronicitySynchronous,
1363         "synchronous",
1364         "Run synchronous",
1365     },
1366     {
1367         eScriptedCommandSynchronicityAsynchronous,
1368         "asynchronous",
1369         "Run asynchronous",
1370     },
1371     {
1372         eScriptedCommandSynchronicityCurrentValue,
1373         "current",
1374         "Do not alter current setting",
1375     },
1376 };
1377 
1378 static constexpr OptionEnumValues ScriptSynchroType() {
1379   return OptionEnumValues(g_script_synchro_type);
1380 }
1381 
1382 #define LLDB_OPTIONS_script_add
1383 #include "CommandOptions.inc"
1384 
1385 class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1386                                        public IOHandlerDelegateMultiline {
1387 public:
1388   CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1389       : CommandObjectParsed(interpreter, "command script add",
1390                             "Add a scripted function as an LLDB command.",
1391                             "Add a scripted function as an lldb command. "
1392                             "If you provide a single argument, the command "
1393                             "will be added at the root level of the command "
1394                             "hierarchy.  If there are more arguments they "
1395                             "must be a path to a user-added container "
1396                             "command, and the last element will be the new "
1397                             "command name."),
1398         IOHandlerDelegateMultiline("DONE"), m_options() {
1399     CommandArgumentEntry arg1;
1400     CommandArgumentData cmd_arg;
1401 
1402     // This is one or more command names, which form the path to the command
1403     // you want to add.
1404     cmd_arg.arg_type = eArgTypeCommand;
1405     cmd_arg.arg_repetition = eArgRepeatPlus;
1406 
1407     // There is only one variant this argument could be; put it into the
1408     // argument entry.
1409     arg1.push_back(cmd_arg);
1410 
1411     // Push the data for the first argument into the m_arguments vector.
1412     m_arguments.push_back(arg1);
1413   }
1414 
1415   ~CommandObjectCommandsScriptAdd() override = default;
1416 
1417   Options *GetOptions() override { return &m_options; }
1418 
1419   void
1420   HandleArgumentCompletion(CompletionRequest &request,
1421                            OptionElementVector &opt_element_vector) override {
1422     CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
1423                                                       opt_element_vector);
1424   }
1425 
1426 protected:
1427   class CommandOptions : public Options {
1428   public:
1429     CommandOptions()
1430         : Options(), m_class_name(), m_funct_name(), m_short_help() {}
1431 
1432     ~CommandOptions() override = default;
1433 
1434     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1435                           ExecutionContext *execution_context) override {
1436       Status error;
1437       const int short_option = m_getopt_table[option_idx].val;
1438 
1439       switch (short_option) {
1440       case 'f':
1441         if (!option_arg.empty())
1442           m_funct_name = std::string(option_arg);
1443         break;
1444       case 'c':
1445         if (!option_arg.empty())
1446           m_class_name = std::string(option_arg);
1447         break;
1448       case 'h':
1449         if (!option_arg.empty())
1450           m_short_help = std::string(option_arg);
1451         break;
1452       case 'o':
1453         m_overwrite = true;
1454         break;
1455       case 's':
1456         m_synchronicity =
1457             (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum(
1458                 option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
1459         if (!error.Success())
1460           error.SetErrorStringWithFormat(
1461               "unrecognized value for synchronicity '%s'",
1462               option_arg.str().c_str());
1463         break;
1464       default:
1465         llvm_unreachable("Unimplemented option");
1466       }
1467 
1468       return error;
1469     }
1470 
1471     void OptionParsingStarting(ExecutionContext *execution_context) override {
1472       m_class_name.clear();
1473       m_funct_name.clear();
1474       m_short_help.clear();
1475       m_overwrite = false;
1476       m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1477     }
1478 
1479     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1480       return llvm::makeArrayRef(g_script_add_options);
1481     }
1482 
1483     // Instance variables to hold the values for command options.
1484 
1485     std::string m_class_name;
1486     std::string m_funct_name;
1487     std::string m_short_help;
1488     bool m_overwrite;
1489     ScriptedCommandSynchronicity m_synchronicity =
1490         eScriptedCommandSynchronicitySynchronous;
1491   };
1492 
1493   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
1494     StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
1495     if (output_sp && interactive) {
1496       output_sp->PutCString(g_python_command_instructions);
1497       output_sp->Flush();
1498     }
1499   }
1500 
1501   void IOHandlerInputComplete(IOHandler &io_handler,
1502                               std::string &data) override {
1503     StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
1504 
1505     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1506     if (interpreter) {
1507 
1508       StringList lines;
1509       lines.SplitIntoLines(data);
1510       if (lines.GetSize() > 0) {
1511         std::string funct_name_str;
1512         if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1513           if (funct_name_str.empty()) {
1514             error_sp->Printf("error: unable to obtain a function name, didn't "
1515                              "add python command.\n");
1516             error_sp->Flush();
1517           } else {
1518             // everything should be fine now, let's add this alias
1519 
1520             CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
1521                 m_interpreter, m_cmd_name, funct_name_str, m_short_help,
1522                 m_synchronicity));
1523             if (!m_container) {
1524               Status error = m_interpreter.AddUserCommand(
1525                   m_cmd_name, command_obj_sp, m_overwrite);
1526               if (error.Fail()) {
1527                 error_sp->Printf("error: unable to add selected command: '%s'",
1528                                  error.AsCString());
1529                 error_sp->Flush();
1530               }
1531             } else {
1532               llvm::Error llvm_error = m_container->LoadUserSubcommand(
1533                   m_cmd_name, command_obj_sp, m_overwrite);
1534               if (llvm_error) {
1535                 error_sp->Printf("error: unable to add selected command: '%s'",
1536                                llvm::toString(std::move(llvm_error)).c_str());
1537                 error_sp->Flush();
1538               }
1539             }
1540           }
1541         } else {
1542           error_sp->Printf(
1543               "error: unable to create function, didn't add python command\n");
1544           error_sp->Flush();
1545         }
1546       } else {
1547         error_sp->Printf("error: empty function, didn't add python command\n");
1548         error_sp->Flush();
1549       }
1550     } else {
1551       error_sp->Printf(
1552           "error: script interpreter missing, didn't add python command\n");
1553       error_sp->Flush();
1554     }
1555 
1556     io_handler.SetIsDone(true);
1557   }
1558 
1559   bool DoExecute(Args &command, CommandReturnObject &result) override {
1560     if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) {
1561       result.AppendError("only scripting language supported for scripted "
1562                          "commands is currently Python");
1563       return false;
1564     }
1565 
1566     if (command.GetArgumentCount() == 0) {
1567       result.AppendError("'command script add' requires at least one argument");
1568       return false;
1569     }
1570     // Store the options in case we get multi-line input
1571     m_overwrite = m_options.m_overwrite;
1572     Status path_error;
1573     m_container = GetCommandInterpreter().VerifyUserMultiwordCmdPath(
1574         command, true, path_error);
1575 
1576     if (path_error.Fail()) {
1577       result.AppendErrorWithFormat("error in command path: %s",
1578                                    path_error.AsCString());
1579       return false;
1580     }
1581 
1582     if (!m_container) {
1583       // This is getting inserted into the root of the interpreter.
1584       m_cmd_name = std::string(command[0].ref());
1585     } else {
1586       size_t num_args = command.GetArgumentCount();
1587       m_cmd_name = std::string(command[num_args - 1].ref());
1588     }
1589 
1590     m_short_help.assign(m_options.m_short_help);
1591     m_synchronicity = m_options.m_synchronicity;
1592 
1593     // Handle the case where we prompt for the script code first:
1594     if (m_options.m_class_name.empty() && m_options.m_funct_name.empty()) {
1595       m_interpreter.GetPythonCommandsFromIOHandler("     ", // Prompt
1596                                                    *this);  // IOHandlerDelegate
1597       return result.Succeeded();
1598     }
1599 
1600     CommandObjectSP new_cmd_sp;
1601     if (m_options.m_class_name.empty()) {
1602       new_cmd_sp.reset(new CommandObjectPythonFunction(
1603           m_interpreter, m_cmd_name, m_options.m_funct_name,
1604           m_options.m_short_help, m_synchronicity));
1605     } else {
1606       ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1607       if (!interpreter) {
1608         result.AppendError("cannot find ScriptInterpreter");
1609         return false;
1610       }
1611 
1612       auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1613           m_options.m_class_name.c_str());
1614       if (!cmd_obj_sp) {
1615         result.AppendError("cannot create helper object");
1616         return false;
1617       }
1618 
1619       new_cmd_sp.reset(new CommandObjectScriptingObject(
1620           m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1621     }
1622 
1623     // Assume we're going to succeed...
1624     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1625     if (!m_container) {
1626       Status add_error =
1627           m_interpreter.AddUserCommand(m_cmd_name, new_cmd_sp, m_overwrite);
1628       if (add_error.Fail())
1629         result.AppendErrorWithFormat("cannot add command: %s",
1630                                      add_error.AsCString());
1631     } else {
1632       llvm::Error llvm_error =
1633           m_container->LoadUserSubcommand(m_cmd_name, new_cmd_sp, m_overwrite);
1634       if (llvm_error)
1635         result.AppendErrorWithFormat("cannot add command: %s",
1636                                      llvm::toString(std::move(llvm_error)).c_str());
1637     }
1638     return result.Succeeded();
1639   }
1640 
1641   CommandOptions m_options;
1642   std::string m_cmd_name;
1643   CommandObjectMultiword *m_container = nullptr;
1644   std::string m_short_help;
1645   bool m_overwrite;
1646   ScriptedCommandSynchronicity m_synchronicity;
1647 };
1648 
1649 // CommandObjectCommandsScriptList
1650 
1651 class CommandObjectCommandsScriptList : public CommandObjectParsed {
1652 public:
1653   CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1654       : CommandObjectParsed(interpreter, "command script list",
1655                             "List defined top-level scripted commands.",
1656                             nullptr) {}
1657 
1658   ~CommandObjectCommandsScriptList() override = default;
1659 
1660   bool DoExecute(Args &command, CommandReturnObject &result) override {
1661     if (command.GetArgumentCount() != 0) {
1662       result.AppendError("'command script list' doesn't take any arguments");
1663       return false;
1664     }
1665 
1666     m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1667 
1668     result.SetStatus(eReturnStatusSuccessFinishResult);
1669 
1670     return true;
1671   }
1672 };
1673 
1674 // CommandObjectCommandsScriptClear
1675 
1676 class CommandObjectCommandsScriptClear : public CommandObjectParsed {
1677 public:
1678   CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1679       : CommandObjectParsed(interpreter, "command script clear",
1680                             "Delete all scripted commands.", nullptr) {}
1681 
1682   ~CommandObjectCommandsScriptClear() override = default;
1683 
1684 protected:
1685   bool DoExecute(Args &command, CommandReturnObject &result) override {
1686     if (command.GetArgumentCount() != 0) {
1687       result.AppendError("'command script clear' doesn't take any arguments");
1688       return false;
1689     }
1690 
1691     m_interpreter.RemoveAllUser();
1692 
1693     result.SetStatus(eReturnStatusSuccessFinishResult);
1694 
1695     return true;
1696   }
1697 };
1698 
1699 // CommandObjectCommandsScriptDelete
1700 
1701 class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
1702 public:
1703   CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1704       : CommandObjectParsed(
1705             interpreter, "command script delete",
1706             "Delete a scripted command by specifying the path to the command.",
1707             nullptr) {
1708     CommandArgumentEntry arg1;
1709     CommandArgumentData cmd_arg;
1710 
1711     // This is a list of command names forming the path to the command
1712     // to be deleted.
1713     cmd_arg.arg_type = eArgTypeCommand;
1714     cmd_arg.arg_repetition = eArgRepeatPlus;
1715 
1716     // There is only one variant this argument could be; put it into the
1717     // argument entry.
1718     arg1.push_back(cmd_arg);
1719 
1720     // Push the data for the first argument into the m_arguments vector.
1721     m_arguments.push_back(arg1);
1722   }
1723 
1724   ~CommandObjectCommandsScriptDelete() override = default;
1725 
1726   void
1727   HandleArgumentCompletion(CompletionRequest &request,
1728                            OptionElementVector &opt_element_vector) override {
1729     CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
1730                                                       opt_element_vector);
1731   }
1732 
1733 protected:
1734   bool DoExecute(Args &command, CommandReturnObject &result) override {
1735 
1736     llvm::StringRef root_cmd = command[0].ref();
1737     size_t num_args = command.GetArgumentCount();
1738 
1739     if (root_cmd.empty()) {
1740       result.AppendErrorWithFormat("empty root command name");
1741       return false;
1742     }
1743     if (!m_interpreter.HasUserCommands() &&
1744         !m_interpreter.HasUserMultiwordCommands()) {
1745       result.AppendErrorWithFormat("can only delete user defined commands, "
1746                                    "but no user defined commands found");
1747       return false;
1748     }
1749 
1750     CommandObjectSP cmd_sp = m_interpreter.GetCommandSPExact(root_cmd);
1751     if (!cmd_sp) {
1752       result.AppendErrorWithFormat("command '%s' not found.",
1753                                    command[0].c_str());
1754       return false;
1755     }
1756     if (!cmd_sp->IsUserCommand()) {
1757       result.AppendErrorWithFormat("command '%s' is not a user command.",
1758                                    command[0].c_str());
1759       return false;
1760     }
1761     if (cmd_sp->GetAsMultiwordCommand() && num_args == 1) {
1762       result.AppendErrorWithFormat("command '%s' is a multi-word command.\n "
1763                                    "Delete with \"command container delete\"",
1764                                    command[0].c_str());
1765       return false;
1766     }
1767 
1768     if (command.GetArgumentCount() == 1) {
1769       m_interpreter.RemoveUser(root_cmd);
1770       result.SetStatus(eReturnStatusSuccessFinishResult);
1771       return true;
1772     }
1773     // We're deleting a command from a multiword command.  Verify the command
1774     // path:
1775     Status error;
1776     CommandObjectMultiword *container =
1777         GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
1778                                                            error);
1779     if (error.Fail()) {
1780       result.AppendErrorWithFormat("could not resolve command path: %s",
1781                                    error.AsCString());
1782       return false;
1783     }
1784     if (!container) {
1785       // This means that command only had a leaf command, so the container is
1786       // the root.  That should have been handled above.
1787       result.AppendErrorWithFormat("could not find a container for '%s'",
1788                                    command[0].c_str());
1789       return false;
1790     }
1791     const char *leaf_cmd = command[num_args - 1].c_str();
1792     llvm::Error llvm_error = container->RemoveUserSubcommand(leaf_cmd,
1793                                             /* multiword not okay */ false);
1794     if (llvm_error) {
1795       result.AppendErrorWithFormat("could not delete command '%s': %s",
1796                                    leaf_cmd,
1797                                    llvm::toString(std::move(llvm_error)).c_str());
1798       return false;
1799     }
1800 
1801     Stream &out_stream = result.GetOutputStream();
1802 
1803     out_stream << "Deleted command:";
1804     for (size_t idx = 0; idx < num_args; idx++) {
1805       out_stream << ' ';
1806       out_stream << command[idx].c_str();
1807     }
1808     out_stream << '\n';
1809     result.SetStatus(eReturnStatusSuccessFinishResult);
1810     return true;
1811   }
1812 };
1813 
1814 #pragma mark CommandObjectMultiwordCommandsScript
1815 
1816 // CommandObjectMultiwordCommandsScript
1817 
1818 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
1819 public:
1820   CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1821       : CommandObjectMultiword(
1822             interpreter, "command script",
1823             "Commands for managing custom "
1824             "commands implemented by "
1825             "interpreter scripts.",
1826             "command script <subcommand> [<subcommand-options>]") {
1827     LoadSubCommand("add", CommandObjectSP(
1828                               new CommandObjectCommandsScriptAdd(interpreter)));
1829     LoadSubCommand(
1830         "delete",
1831         CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1832     LoadSubCommand(
1833         "clear",
1834         CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1835     LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1836                                interpreter)));
1837     LoadSubCommand(
1838         "import",
1839         CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1840   }
1841 
1842   ~CommandObjectMultiwordCommandsScript() override = default;
1843 };
1844 
1845 #pragma mark CommandObjectCommandContainer
1846 #define LLDB_OPTIONS_container_add
1847 #include "CommandOptions.inc"
1848 
1849 class CommandObjectCommandsContainerAdd : public CommandObjectParsed {
1850 public:
1851   CommandObjectCommandsContainerAdd(CommandInterpreter &interpreter)
1852       : CommandObjectParsed(
1853             interpreter, "command container add",
1854             "Add a container command to lldb.  Adding to built-"
1855             "in container commands is not allowed.",
1856             "command container add [[path1]...] container-name") {
1857     CommandArgumentEntry arg1;
1858     CommandArgumentData cmd_arg;
1859 
1860     // This is one or more command names, which form the path to the command
1861     // you want to add.
1862     cmd_arg.arg_type = eArgTypeCommand;
1863     cmd_arg.arg_repetition = eArgRepeatPlus;
1864 
1865     // There is only one variant this argument could be; put it into the
1866     // argument entry.
1867     arg1.push_back(cmd_arg);
1868 
1869     // Push the data for the first argument into the m_arguments vector.
1870     m_arguments.push_back(arg1);
1871   }
1872 
1873   ~CommandObjectCommandsContainerAdd() override = default;
1874 
1875   Options *GetOptions() override { return &m_options; }
1876 
1877   void
1878   HandleArgumentCompletion(CompletionRequest &request,
1879                            OptionElementVector &opt_element_vector) override {
1880     CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
1881                                                       opt_element_vector);
1882   }
1883 
1884 protected:
1885   class CommandOptions : public Options {
1886   public:
1887     CommandOptions() : Options(), m_short_help(), m_long_help() {}
1888 
1889     ~CommandOptions() override = default;
1890 
1891     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1892                           ExecutionContext *execution_context) override {
1893       Status error;
1894       const int short_option = m_getopt_table[option_idx].val;
1895 
1896       switch (short_option) {
1897       case 'h':
1898         if (!option_arg.empty())
1899           m_short_help = std::string(option_arg);
1900         break;
1901       case 'o':
1902         m_overwrite = true;
1903         break;
1904       case 'H':
1905         if (!option_arg.empty())
1906           m_long_help = std::string(option_arg);
1907         break;
1908       default:
1909         llvm_unreachable("Unimplemented option");
1910       }
1911 
1912       return error;
1913     }
1914 
1915     void OptionParsingStarting(ExecutionContext *execution_context) override {
1916       m_short_help.clear();
1917       m_long_help.clear();
1918       m_overwrite = false;
1919     }
1920 
1921     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1922       return llvm::makeArrayRef(g_container_add_options);
1923     }
1924 
1925     // Instance variables to hold the values for command options.
1926 
1927     std::string m_short_help;
1928     std::string m_long_help;
1929     bool m_overwrite = false;
1930   };
1931   bool DoExecute(Args &command, CommandReturnObject &result) override {
1932     size_t num_args = command.GetArgumentCount();
1933 
1934     if (num_args == 0) {
1935       result.AppendError("no command was specified");
1936       return false;
1937     }
1938 
1939     if (num_args == 1) {
1940       // We're adding this as a root command, so use the interpreter.
1941       const char *cmd_name = command.GetArgumentAtIndex(0);
1942       auto cmd_sp = CommandObjectSP(new CommandObjectMultiword(
1943           GetCommandInterpreter(), cmd_name, m_options.m_short_help.c_str(),
1944           m_options.m_long_help.c_str()));
1945       cmd_sp->GetAsMultiwordCommand()->SetRemovable(true);
1946       Status add_error = GetCommandInterpreter().AddUserCommand(
1947           cmd_name, cmd_sp, m_options.m_overwrite);
1948       if (add_error.Fail()) {
1949         result.AppendErrorWithFormat("error adding command: %s",
1950                                      add_error.AsCString());
1951         return false;
1952       }
1953       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1954       return true;
1955     }
1956 
1957     // We're adding this to a subcommand, first find the subcommand:
1958     Status path_error;
1959     CommandObjectMultiword *add_to_me =
1960         GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
1961                                                            path_error);
1962 
1963     if (!add_to_me) {
1964       result.AppendErrorWithFormat("error adding command: %s",
1965                                    path_error.AsCString());
1966       return false;
1967     }
1968 
1969     const char *cmd_name = command.GetArgumentAtIndex(num_args - 1);
1970     auto cmd_sp = CommandObjectSP(new CommandObjectMultiword(
1971         GetCommandInterpreter(), cmd_name, m_options.m_short_help.c_str(),
1972         m_options.m_long_help.c_str()));
1973     llvm::Error llvm_error =
1974         add_to_me->LoadUserSubcommand(cmd_name, cmd_sp, m_options.m_overwrite);
1975     if (llvm_error) {
1976       result.AppendErrorWithFormat("error adding subcommand: %s",
1977                                    llvm::toString(std::move(llvm_error)).c_str());
1978       return false;
1979     }
1980 
1981     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1982     return true;
1983   }
1984 
1985 private:
1986   CommandOptions m_options;
1987 };
1988 
1989 #define LLDB_OPTIONS_multiword_delete
1990 #include "CommandOptions.inc"
1991 class CommandObjectCommandsContainerDelete : public CommandObjectParsed {
1992 public:
1993   CommandObjectCommandsContainerDelete(CommandInterpreter &interpreter)
1994       : CommandObjectParsed(
1995             interpreter, "command container delete",
1996             "Delete a container command previously added to "
1997             "lldb.",
1998             "command container delete [[path1] ...] container-cmd") {
1999     CommandArgumentEntry arg1;
2000     CommandArgumentData cmd_arg;
2001 
2002     // This is one or more command names, which form the path to the command
2003     // you want to add.
2004     cmd_arg.arg_type = eArgTypeCommand;
2005     cmd_arg.arg_repetition = eArgRepeatPlus;
2006 
2007     // There is only one variant this argument could be; put it into the
2008     // argument entry.
2009     arg1.push_back(cmd_arg);
2010 
2011     // Push the data for the first argument into the m_arguments vector.
2012     m_arguments.push_back(arg1);
2013   }
2014 
2015   ~CommandObjectCommandsContainerDelete() override = default;
2016 
2017   void
2018   HandleArgumentCompletion(CompletionRequest &request,
2019                            OptionElementVector &opt_element_vector) override {
2020     CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
2021                                                       opt_element_vector);
2022   }
2023 
2024 protected:
2025   bool DoExecute(Args &command, CommandReturnObject &result) override {
2026     size_t num_args = command.GetArgumentCount();
2027 
2028     if (num_args == 0) {
2029       result.AppendError("No command was specified.");
2030       return false;
2031     }
2032 
2033     if (num_args == 1) {
2034       // We're removing a root command, so we need to delete it from the
2035       // interpreter.
2036       const char *cmd_name = command.GetArgumentAtIndex(0);
2037       // Let's do a little more work here so we can do better error reporting.
2038       CommandInterpreter &interp = GetCommandInterpreter();
2039       CommandObjectSP cmd_sp = interp.GetCommandSPExact(cmd_name);
2040       if (!cmd_sp) {
2041         result.AppendErrorWithFormat("container command %s doesn't exist.",
2042                                      cmd_name);
2043         return false;
2044       }
2045       if (!cmd_sp->IsUserCommand()) {
2046         result.AppendErrorWithFormat(
2047             "container command %s is not a user command", cmd_name);
2048         return false;
2049       }
2050       if (!cmd_sp->GetAsMultiwordCommand()) {
2051         result.AppendErrorWithFormat("command %s is not a container command",
2052                                      cmd_name);
2053         return false;
2054       }
2055 
2056       bool did_remove = GetCommandInterpreter().RemoveUserMultiword(cmd_name);
2057       if (!did_remove) {
2058         result.AppendErrorWithFormat("error removing command %s.", cmd_name);
2059         return false;
2060       }
2061 
2062       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2063       return true;
2064     }
2065 
2066     // We're removing a subcommand, first find the subcommand's owner:
2067     Status path_error;
2068     CommandObjectMultiword *container =
2069         GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
2070                                                            path_error);
2071 
2072     if (!container) {
2073       result.AppendErrorWithFormat("error removing container command: %s",
2074                                    path_error.AsCString());
2075       return false;
2076     }
2077     const char *leaf = command.GetArgumentAtIndex(num_args - 1);
2078     llvm::Error llvm_error =
2079         container->RemoveUserSubcommand(leaf, /* multiword okay */ true);
2080     if (llvm_error) {
2081       result.AppendErrorWithFormat("error removing container command: %s",
2082                                    llvm::toString(std::move(llvm_error)).c_str());
2083       return false;
2084     }
2085     result.SetStatus(eReturnStatusSuccessFinishNoResult);
2086     return true;
2087   }
2088 };
2089 
2090 class CommandObjectCommandContainer : public CommandObjectMultiword {
2091 public:
2092   CommandObjectCommandContainer(CommandInterpreter &interpreter)
2093       : CommandObjectMultiword(
2094             interpreter, "command container",
2095             "Commands for adding container commands to lldb.  "
2096             "Container commands are containers for other commands.  You can"
2097             "add nested container commands by specifying a command path, but "
2098             "but you can't add commands into the built-in command hierarchy.",
2099             "command container <subcommand> [<subcommand-options>]") {
2100     LoadSubCommand("add", CommandObjectSP(new CommandObjectCommandsContainerAdd(
2101                               interpreter)));
2102     LoadSubCommand(
2103         "delete",
2104         CommandObjectSP(new CommandObjectCommandsContainerDelete(interpreter)));
2105   }
2106 
2107   ~CommandObjectCommandContainer() override = default;
2108 };
2109 
2110 #pragma mark CommandObjectMultiwordCommands
2111 
2112 // CommandObjectMultiwordCommands
2113 
2114 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
2115     CommandInterpreter &interpreter)
2116     : CommandObjectMultiword(interpreter, "command",
2117                              "Commands for managing custom LLDB commands.",
2118                              "command <subcommand> [<subcommand-options>]") {
2119   LoadSubCommand("source",
2120                  CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
2121   LoadSubCommand("alias",
2122                  CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
2123   LoadSubCommand("unalias", CommandObjectSP(
2124                                 new CommandObjectCommandsUnalias(interpreter)));
2125   LoadSubCommand("delete",
2126                  CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
2127   LoadSubCommand("container", CommandObjectSP(new CommandObjectCommandContainer(
2128                                   interpreter)));
2129   LoadSubCommand(
2130       "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
2131   LoadSubCommand(
2132       "script",
2133       CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
2134 }
2135 
2136 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
2137