xref: /llvm-project/lldb/source/Commands/CommandObjectCommands.cpp (revision d518ed42ae85786c371fd4578f72ab7eb286cb30)
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     // Look up the command using command's name first.  This is to resolve
489     // aliases when you are making nested aliases.  But if you don't find
490     // it that way, then it wasn't an alias and we can just use the object
491     // we were passed in.
492     CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact(
493             cmd_obj.GetCommandName(), include_aliases);
494     if (!cmd_obj_sp)
495       cmd_obj_sp = cmd_obj.shared_from_this();
496 
497     if (m_interpreter.AliasExists(alias_command) ||
498         m_interpreter.UserCommandExists(alias_command)) {
499       result.AppendWarningWithFormat(
500           "Overwriting existing definition for '%s'.\n",
501           alias_command.str().c_str());
502     }
503     if (CommandAlias *alias = m_interpreter.AddAlias(
504             alias_command, cmd_obj_sp, raw_command_string)) {
505       if (m_command_options.m_help.OptionWasSet())
506         alias->SetHelp(m_command_options.m_help.GetCurrentValue());
507       if (m_command_options.m_long_help.OptionWasSet())
508         alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
509       result.SetStatus(eReturnStatusSuccessFinishNoResult);
510     } else {
511       result.AppendError("Unable to create requested alias.\n");
512     }
513     return result.Succeeded();
514   }
515 
516   bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
517     size_t argc = args.GetArgumentCount();
518 
519     if (argc < 2) {
520       result.AppendError("'command alias' requires at least two arguments");
521       return false;
522     }
523 
524     // Save these in std::strings since we're going to shift them off.
525     const std::string alias_command(std::string(args[0].ref()));
526     const std::string actual_command(std::string(args[1].ref()));
527 
528     args.Shift(); // Shift the alias command word off the argument vector.
529     args.Shift(); // Shift the old command word off the argument vector.
530 
531     // Verify that the command is alias'able, and get the appropriate command
532     // object.
533 
534     if (m_interpreter.CommandExists(alias_command)) {
535       result.AppendErrorWithFormat(
536           "'%s' is a permanent debugger command and cannot be redefined.\n",
537           alias_command.c_str());
538       return false;
539     }
540 
541     if (m_interpreter.UserMultiwordCommandExists(alias_command)) {
542       result.AppendErrorWithFormat(
543           "'%s' is user container command and cannot be overwritten.\n"
544           "Delete it first with 'command container delete'",
545           alias_command.c_str());
546       return false;
547     }
548 
549     CommandObjectSP command_obj_sp(
550         m_interpreter.GetCommandSPExact(actual_command, true));
551     CommandObjectSP subcommand_obj_sp;
552     bool use_subcommand = false;
553     if (!command_obj_sp) {
554       result.AppendErrorWithFormat("'%s' is not an existing command.\n",
555                                    actual_command.c_str());
556       return false;
557     }
558     CommandObject *cmd_obj = command_obj_sp.get();
559     CommandObject *sub_cmd_obj = nullptr;
560     OptionArgVectorSP option_arg_vector_sp =
561         OptionArgVectorSP(new OptionArgVector);
562 
563     while (cmd_obj->IsMultiwordObject() && !args.empty()) {
564       auto sub_command = args[0].ref();
565       assert(!sub_command.empty());
566       subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command);
567       if (!subcommand_obj_sp) {
568         result.AppendErrorWithFormat(
569             "'%s' is not a valid sub-command of '%s'.  "
570             "Unable to create alias.\n",
571             args[0].c_str(), actual_command.c_str());
572         return false;
573       }
574 
575       sub_cmd_obj = subcommand_obj_sp.get();
576       use_subcommand = true;
577       args.Shift(); // Shift the sub_command word off the argument vector.
578       cmd_obj = sub_cmd_obj;
579     }
580 
581     // Verify & handle any options/arguments passed to the alias command
582 
583     std::string args_string;
584 
585     if (!args.empty()) {
586       CommandObjectSP tmp_sp =
587           m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName());
588       if (use_subcommand)
589         tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName());
590 
591       args.GetCommandString(args_string);
592     }
593 
594     if (m_interpreter.AliasExists(alias_command) ||
595         m_interpreter.UserCommandExists(alias_command)) {
596       result.AppendWarningWithFormat(
597           "Overwriting existing definition for '%s'.\n", alias_command.c_str());
598     }
599 
600     if (CommandAlias *alias = m_interpreter.AddAlias(
601             alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp,
602             args_string)) {
603       if (m_command_options.m_help.OptionWasSet())
604         alias->SetHelp(m_command_options.m_help.GetCurrentValue());
605       if (m_command_options.m_long_help.OptionWasSet())
606         alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
607       result.SetStatus(eReturnStatusSuccessFinishNoResult);
608     } else {
609       result.AppendError("Unable to create requested alias.\n");
610       return false;
611     }
612 
613     return result.Succeeded();
614   }
615 };
616 
617 #pragma mark CommandObjectCommandsUnalias
618 // CommandObjectCommandsUnalias
619 
620 class CommandObjectCommandsUnalias : public CommandObjectParsed {
621 public:
622   CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
623       : CommandObjectParsed(
624             interpreter, "command unalias",
625             "Delete one or more custom commands defined by 'command alias'.",
626             nullptr) {
627     CommandArgumentEntry arg;
628     CommandArgumentData alias_arg;
629 
630     // Define the first (and only) variant of this arg.
631     alias_arg.arg_type = eArgTypeAliasName;
632     alias_arg.arg_repetition = eArgRepeatPlain;
633 
634     // There is only one variant this argument could be; put it into the
635     // argument entry.
636     arg.push_back(alias_arg);
637 
638     // Push the data for the first argument into the m_arguments vector.
639     m_arguments.push_back(arg);
640   }
641 
642   ~CommandObjectCommandsUnalias() override = default;
643 
644   void
645   HandleArgumentCompletion(CompletionRequest &request,
646                            OptionElementVector &opt_element_vector) override {
647     if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
648       return;
649 
650     for (const auto &ent : m_interpreter.GetAliases()) {
651       request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp());
652     }
653   }
654 
655 protected:
656   bool DoExecute(Args &args, CommandReturnObject &result) override {
657     CommandObject::CommandMap::iterator pos;
658     CommandObject *cmd_obj;
659 
660     if (args.empty()) {
661       result.AppendError("must call 'unalias' with a valid alias");
662       return false;
663     }
664 
665     auto command_name = args[0].ref();
666     cmd_obj = m_interpreter.GetCommandObject(command_name);
667     if (!cmd_obj) {
668       result.AppendErrorWithFormat(
669           "'%s' is not a known command.\nTry 'help' to see a "
670           "current list of commands.\n",
671           args[0].c_str());
672       return false;
673     }
674 
675     if (m_interpreter.CommandExists(command_name)) {
676       if (cmd_obj->IsRemovable()) {
677         result.AppendErrorWithFormat(
678             "'%s' is not an alias, it is a debugger command which can be "
679             "removed using the 'command delete' command.\n",
680             args[0].c_str());
681       } else {
682         result.AppendErrorWithFormat(
683             "'%s' is a permanent debugger command and cannot be removed.\n",
684             args[0].c_str());
685       }
686       return false;
687     }
688 
689     if (!m_interpreter.RemoveAlias(command_name)) {
690       if (m_interpreter.AliasExists(command_name))
691         result.AppendErrorWithFormat(
692             "Error occurred while attempting to unalias '%s'.\n",
693             args[0].c_str());
694       else
695         result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
696                                      args[0].c_str());
697       return false;
698     }
699 
700     result.SetStatus(eReturnStatusSuccessFinishNoResult);
701     return result.Succeeded();
702   }
703 };
704 
705 #pragma mark CommandObjectCommandsDelete
706 // CommandObjectCommandsDelete
707 
708 class CommandObjectCommandsDelete : public CommandObjectParsed {
709 public:
710   CommandObjectCommandsDelete(CommandInterpreter &interpreter)
711       : CommandObjectParsed(
712             interpreter, "command delete",
713             "Delete one or more custom commands defined by 'command regex'.",
714             nullptr) {
715     CommandArgumentEntry arg;
716     CommandArgumentData alias_arg;
717 
718     // Define the first (and only) variant of this arg.
719     alias_arg.arg_type = eArgTypeCommandName;
720     alias_arg.arg_repetition = eArgRepeatPlain;
721 
722     // There is only one variant this argument could be; put it into the
723     // argument entry.
724     arg.push_back(alias_arg);
725 
726     // Push the data for the first argument into the m_arguments vector.
727     m_arguments.push_back(arg);
728   }
729 
730   ~CommandObjectCommandsDelete() override = default;
731 
732   void
733   HandleArgumentCompletion(CompletionRequest &request,
734                            OptionElementVector &opt_element_vector) override {
735     if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
736       return;
737 
738     for (const auto &ent : m_interpreter.GetCommands()) {
739       if (ent.second->IsRemovable())
740         request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp());
741     }
742   }
743 
744 protected:
745   bool DoExecute(Args &args, CommandReturnObject &result) override {
746     CommandObject::CommandMap::iterator pos;
747 
748     if (args.empty()) {
749       result.AppendErrorWithFormat("must call '%s' with one or more valid user "
750                                    "defined regular expression command names",
751                                    GetCommandName().str().c_str());
752       return false;
753     }
754 
755     auto command_name = args[0].ref();
756     if (!m_interpreter.CommandExists(command_name)) {
757       StreamString error_msg_stream;
758       const bool generate_upropos = true;
759       const bool generate_type_lookup = false;
760       CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
761           &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(),
762           generate_upropos, generate_type_lookup);
763       result.AppendError(error_msg_stream.GetString());
764       return false;
765     }
766 
767     if (!m_interpreter.RemoveCommand(command_name)) {
768       result.AppendErrorWithFormat(
769           "'%s' is a permanent debugger command and cannot be removed.\n",
770           args[0].c_str());
771       return false;
772     }
773 
774     result.SetStatus(eReturnStatusSuccessFinishNoResult);
775     return true;
776   }
777 };
778 
779 // CommandObjectCommandsAddRegex
780 
781 #define LLDB_OPTIONS_regex
782 #include "CommandOptions.inc"
783 
784 #pragma mark CommandObjectCommandsAddRegex
785 
786 class CommandObjectCommandsAddRegex : public CommandObjectParsed,
787                                       public IOHandlerDelegateMultiline {
788 public:
789   CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
790       : CommandObjectParsed(
791             interpreter, "command regex",
792             "Define a custom command in terms of "
793             "existing commands by matching "
794             "regular expressions.",
795             "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
796         IOHandlerDelegateMultiline("",
797                                    IOHandlerDelegate::Completion::LLDBCommand) {
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     CommandArgumentData thread_arg{eArgTypeSEDStylePair, eArgRepeatOptional};
831     m_arguments.push_back({thread_arg});
832   }
833 
834   ~CommandObjectCommandsAddRegex() override = default;
835 
836 protected:
837   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
838     StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
839     if (output_sp && interactive) {
840       output_sp->PutCString("Enter one or more sed substitution commands in "
841                             "the form: 's/<regex>/<subst>/'.\nTerminate the "
842                             "substitution list with an empty line.\n");
843       output_sp->Flush();
844     }
845   }
846 
847   void IOHandlerInputComplete(IOHandler &io_handler,
848                               std::string &data) override {
849     io_handler.SetIsDone(true);
850     if (m_regex_cmd_up) {
851       StringList lines;
852       if (lines.SplitIntoLines(data)) {
853         bool check_only = false;
854         for (const std::string &line : lines) {
855           Status error = AppendRegexSubstitution(line, check_only);
856           if (error.Fail()) {
857             if (!GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) {
858               StreamSP out_stream = GetDebugger().GetAsyncOutputStream();
859               out_stream->Printf("error: %s\n", error.AsCString());
860             }
861           }
862         }
863       }
864       if (m_regex_cmd_up->HasRegexEntries()) {
865         CommandObjectSP cmd_sp(m_regex_cmd_up.release());
866         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
867       }
868     }
869   }
870 
871   bool DoExecute(Args &command, CommandReturnObject &result) override {
872     const size_t argc = command.GetArgumentCount();
873     if (argc == 0) {
874       result.AppendError("usage: 'command regex <command-name> "
875                          "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
876       return false;
877     }
878 
879     Status error;
880     auto name = command[0].ref();
881     m_regex_cmd_up = std::make_unique<CommandObjectRegexCommand>(
882         m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0,
883         true);
884 
885     if (argc == 1) {
886       Debugger &debugger = GetDebugger();
887       bool color_prompt = debugger.GetUseColor();
888       const bool multiple_lines = true; // Get multiple lines
889       IOHandlerSP io_handler_sp(new IOHandlerEditline(
890           debugger, IOHandler::Type::Other,
891           "lldb-regex",          // Name of input reader for history
892           llvm::StringRef("> "), // Prompt
893           llvm::StringRef(),     // Continuation prompt
894           multiple_lines, color_prompt,
895           0, // Don't show line numbers
896           *this));
897 
898       if (io_handler_sp) {
899         debugger.RunIOHandlerAsync(io_handler_sp);
900         result.SetStatus(eReturnStatusSuccessFinishNoResult);
901       }
902     } else {
903       for (auto &entry : command.entries().drop_front()) {
904         bool check_only = false;
905         error = AppendRegexSubstitution(entry.ref(), check_only);
906         if (error.Fail())
907           break;
908       }
909 
910       if (error.Success()) {
911         AddRegexCommandToInterpreter();
912       }
913     }
914     if (error.Fail()) {
915       result.AppendError(error.AsCString());
916     }
917 
918     return result.Succeeded();
919   }
920 
921   Status AppendRegexSubstitution(const llvm::StringRef &regex_sed,
922                                  bool check_only) {
923     Status error;
924 
925     if (!m_regex_cmd_up) {
926       error.SetErrorStringWithFormat(
927           "invalid regular expression command object for: '%.*s'",
928           (int)regex_sed.size(), regex_sed.data());
929       return error;
930     }
931 
932     size_t regex_sed_size = regex_sed.size();
933 
934     if (regex_sed_size <= 1) {
935       error.SetErrorStringWithFormat(
936           "regular expression substitution string is too short: '%.*s'",
937           (int)regex_sed.size(), regex_sed.data());
938       return error;
939     }
940 
941     if (regex_sed[0] != 's') {
942       error.SetErrorStringWithFormat("regular expression substitution string "
943                                      "doesn't start with 's': '%.*s'",
944                                      (int)regex_sed.size(), regex_sed.data());
945       return error;
946     }
947     const size_t first_separator_char_pos = 1;
948     // use the char that follows 's' as the regex separator character so we can
949     // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
950     const char separator_char = regex_sed[first_separator_char_pos];
951     const size_t second_separator_char_pos =
952         regex_sed.find(separator_char, first_separator_char_pos + 1);
953 
954     if (second_separator_char_pos == std::string::npos) {
955       error.SetErrorStringWithFormat(
956           "missing second '%c' separator char after '%.*s' in '%.*s'",
957           separator_char,
958           (int)(regex_sed.size() - first_separator_char_pos - 1),
959           regex_sed.data() + (first_separator_char_pos + 1),
960           (int)regex_sed.size(), regex_sed.data());
961       return error;
962     }
963 
964     const size_t third_separator_char_pos =
965         regex_sed.find(separator_char, second_separator_char_pos + 1);
966 
967     if (third_separator_char_pos == std::string::npos) {
968       error.SetErrorStringWithFormat(
969           "missing third '%c' separator char after '%.*s' in '%.*s'",
970           separator_char,
971           (int)(regex_sed.size() - second_separator_char_pos - 1),
972           regex_sed.data() + (second_separator_char_pos + 1),
973           (int)regex_sed.size(), regex_sed.data());
974       return error;
975     }
976 
977     if (third_separator_char_pos != regex_sed_size - 1) {
978       // Make sure that everything that follows the last regex separator char
979       if (regex_sed.find_first_not_of("\t\n\v\f\r ",
980                                       third_separator_char_pos + 1) !=
981           std::string::npos) {
982         error.SetErrorStringWithFormat(
983             "extra data found after the '%.*s' regular expression substitution "
984             "string: '%.*s'",
985             (int)third_separator_char_pos + 1, regex_sed.data(),
986             (int)(regex_sed.size() - third_separator_char_pos - 1),
987             regex_sed.data() + (third_separator_char_pos + 1));
988         return error;
989       }
990     } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
991       error.SetErrorStringWithFormat(
992           "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
993           separator_char, separator_char, separator_char, (int)regex_sed.size(),
994           regex_sed.data());
995       return error;
996     } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
997       error.SetErrorStringWithFormat(
998           "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
999           separator_char, separator_char, separator_char, (int)regex_sed.size(),
1000           regex_sed.data());
1001       return error;
1002     }
1003 
1004     if (!check_only) {
1005       std::string regex(std::string(regex_sed.substr(
1006           first_separator_char_pos + 1,
1007           second_separator_char_pos - first_separator_char_pos - 1)));
1008       std::string subst(std::string(regex_sed.substr(
1009           second_separator_char_pos + 1,
1010           third_separator_char_pos - second_separator_char_pos - 1)));
1011       m_regex_cmd_up->AddRegexCommand(regex, subst);
1012     }
1013     return error;
1014   }
1015 
1016   void AddRegexCommandToInterpreter() {
1017     if (m_regex_cmd_up) {
1018       if (m_regex_cmd_up->HasRegexEntries()) {
1019         CommandObjectSP cmd_sp(m_regex_cmd_up.release());
1020         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1021       }
1022     }
1023   }
1024 
1025 private:
1026   std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_up;
1027 
1028   class CommandOptions : public Options {
1029   public:
1030     CommandOptions() = default;
1031 
1032     ~CommandOptions() override = default;
1033 
1034     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1035                           ExecutionContext *execution_context) override {
1036       Status error;
1037       const int short_option = m_getopt_table[option_idx].val;
1038 
1039       switch (short_option) {
1040       case 'h':
1041         m_help.assign(std::string(option_arg));
1042         break;
1043       case 's':
1044         m_syntax.assign(std::string(option_arg));
1045         break;
1046       default:
1047         llvm_unreachable("Unimplemented option");
1048       }
1049 
1050       return error;
1051     }
1052 
1053     void OptionParsingStarting(ExecutionContext *execution_context) override {
1054       m_help.clear();
1055       m_syntax.clear();
1056     }
1057 
1058     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1059       return llvm::makeArrayRef(g_regex_options);
1060     }
1061 
1062     llvm::StringRef GetHelp() { return m_help; }
1063 
1064     llvm::StringRef GetSyntax() { return m_syntax; }
1065 
1066   protected:
1067     // Instance variables to hold the values for command options.
1068 
1069     std::string m_help;
1070     std::string m_syntax;
1071   };
1072 
1073   Options *GetOptions() override { return &m_options; }
1074 
1075   CommandOptions m_options;
1076 };
1077 
1078 class CommandObjectPythonFunction : public CommandObjectRaw {
1079 public:
1080   CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
1081                               std::string funct, std::string help,
1082                               ScriptedCommandSynchronicity synch)
1083       : CommandObjectRaw(interpreter, name), m_function_name(funct),
1084         m_synchro(synch) {
1085     if (!help.empty())
1086       SetHelp(help);
1087     else {
1088       StreamString stream;
1089       stream.Printf("For more information run 'help %s'", name.c_str());
1090       SetHelp(stream.GetString());
1091     }
1092   }
1093 
1094   ~CommandObjectPythonFunction() override = default;
1095 
1096   bool IsRemovable() const override { return true; }
1097 
1098   const std::string &GetFunctionName() { return m_function_name; }
1099 
1100   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1101 
1102   llvm::StringRef GetHelpLong() override {
1103     if (m_fetched_help_long)
1104       return CommandObjectRaw::GetHelpLong();
1105 
1106     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1107     if (!scripter)
1108       return CommandObjectRaw::GetHelpLong();
1109 
1110     std::string docstring;
1111     m_fetched_help_long =
1112         scripter->GetDocumentationForItem(m_function_name.c_str(), docstring);
1113     if (!docstring.empty())
1114       SetHelpLong(docstring);
1115     return CommandObjectRaw::GetHelpLong();
1116   }
1117 
1118 protected:
1119   bool DoExecute(llvm::StringRef raw_command_line,
1120                  CommandReturnObject &result) override {
1121     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1122 
1123     Status error;
1124 
1125     result.SetStatus(eReturnStatusInvalid);
1126 
1127     if (!scripter || !scripter->RunScriptBasedCommand(
1128                          m_function_name.c_str(), raw_command_line, m_synchro,
1129                          result, error, m_exe_ctx)) {
1130       result.AppendError(error.AsCString());
1131     } else {
1132       // Don't change the status if the command already set it...
1133       if (result.GetStatus() == eReturnStatusInvalid) {
1134         if (result.GetOutputData().empty())
1135           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1136         else
1137           result.SetStatus(eReturnStatusSuccessFinishResult);
1138       }
1139     }
1140 
1141     return result.Succeeded();
1142   }
1143 
1144 private:
1145   std::string m_function_name;
1146   ScriptedCommandSynchronicity m_synchro;
1147   bool m_fetched_help_long = false;
1148 };
1149 
1150 class CommandObjectScriptingObject : public CommandObjectRaw {
1151 public:
1152   CommandObjectScriptingObject(CommandInterpreter &interpreter,
1153                                std::string name,
1154                                StructuredData::GenericSP cmd_obj_sp,
1155                                ScriptedCommandSynchronicity synch)
1156       : CommandObjectRaw(interpreter, name), m_cmd_obj_sp(cmd_obj_sp),
1157         m_synchro(synch), m_fetched_help_short(false),
1158         m_fetched_help_long(false) {
1159     StreamString stream;
1160     stream.Printf("For more information run 'help %s'", name.c_str());
1161     SetHelp(stream.GetString());
1162     if (ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter())
1163       GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
1164   }
1165 
1166   ~CommandObjectScriptingObject() override = default;
1167 
1168   bool IsRemovable() const override { return true; }
1169 
1170   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1171 
1172   llvm::StringRef GetHelp() override {
1173     if (m_fetched_help_short)
1174       return CommandObjectRaw::GetHelp();
1175     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1176     if (!scripter)
1177       return CommandObjectRaw::GetHelp();
1178     std::string docstring;
1179     m_fetched_help_short =
1180         scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
1181     if (!docstring.empty())
1182       SetHelp(docstring);
1183 
1184     return CommandObjectRaw::GetHelp();
1185   }
1186 
1187   llvm::StringRef GetHelpLong() override {
1188     if (m_fetched_help_long)
1189       return CommandObjectRaw::GetHelpLong();
1190 
1191     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1192     if (!scripter)
1193       return CommandObjectRaw::GetHelpLong();
1194 
1195     std::string docstring;
1196     m_fetched_help_long =
1197         scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
1198     if (!docstring.empty())
1199       SetHelpLong(docstring);
1200     return CommandObjectRaw::GetHelpLong();
1201   }
1202 
1203 protected:
1204   bool DoExecute(llvm::StringRef raw_command_line,
1205                  CommandReturnObject &result) override {
1206     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1207 
1208     Status error;
1209 
1210     result.SetStatus(eReturnStatusInvalid);
1211 
1212     if (!scripter ||
1213         !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1214                                          m_synchro, result, error, m_exe_ctx)) {
1215       result.AppendError(error.AsCString());
1216     } else {
1217       // Don't change the status if the command already set it...
1218       if (result.GetStatus() == eReturnStatusInvalid) {
1219         if (result.GetOutputData().empty())
1220           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1221         else
1222           result.SetStatus(eReturnStatusSuccessFinishResult);
1223       }
1224     }
1225 
1226     return result.Succeeded();
1227   }
1228 
1229 private:
1230   StructuredData::GenericSP m_cmd_obj_sp;
1231   ScriptedCommandSynchronicity m_synchro;
1232   bool m_fetched_help_short : 1;
1233   bool m_fetched_help_long : 1;
1234 };
1235 
1236 // CommandObjectCommandsScriptImport
1237 #define LLDB_OPTIONS_script_import
1238 #include "CommandOptions.inc"
1239 
1240 class CommandObjectCommandsScriptImport : public CommandObjectParsed {
1241 public:
1242   CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1243       : CommandObjectParsed(interpreter, "command script import",
1244                             "Import a scripting module in LLDB.", nullptr) {
1245     CommandArgumentEntry arg1;
1246     CommandArgumentData cmd_arg;
1247 
1248     // Define the first (and only) variant of this arg.
1249     cmd_arg.arg_type = eArgTypeFilename;
1250     cmd_arg.arg_repetition = eArgRepeatPlus;
1251 
1252     // There is only one variant this argument could be; put it into the
1253     // argument entry.
1254     arg1.push_back(cmd_arg);
1255 
1256     // Push the data for the first argument into the m_arguments vector.
1257     m_arguments.push_back(arg1);
1258   }
1259 
1260   ~CommandObjectCommandsScriptImport() override = default;
1261 
1262   void
1263   HandleArgumentCompletion(CompletionRequest &request,
1264                            OptionElementVector &opt_element_vector) override {
1265     CommandCompletions::InvokeCommonCompletionCallbacks(
1266         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
1267         request, nullptr);
1268   }
1269 
1270   Options *GetOptions() override { return &m_options; }
1271 
1272 protected:
1273   class CommandOptions : public Options {
1274   public:
1275     CommandOptions() = default;
1276 
1277     ~CommandOptions() override = default;
1278 
1279     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1280                           ExecutionContext *execution_context) override {
1281       Status error;
1282       const int short_option = m_getopt_table[option_idx].val;
1283 
1284       switch (short_option) {
1285       case 'r':
1286         // NO-OP
1287         break;
1288       case 'c':
1289         relative_to_command_file = true;
1290         break;
1291       case 's':
1292         silent = true;
1293         break;
1294       default:
1295         llvm_unreachable("Unimplemented option");
1296       }
1297 
1298       return error;
1299     }
1300 
1301     void OptionParsingStarting(ExecutionContext *execution_context) override {
1302       relative_to_command_file = false;
1303     }
1304 
1305     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1306       return llvm::makeArrayRef(g_script_import_options);
1307     }
1308     bool relative_to_command_file = false;
1309     bool silent = false;
1310   };
1311 
1312   bool DoExecute(Args &command, CommandReturnObject &result) override {
1313     if (command.empty()) {
1314       result.AppendError("command script import needs one or more arguments");
1315       return false;
1316     }
1317 
1318     FileSpec source_dir = {};
1319     if (m_options.relative_to_command_file) {
1320       source_dir = GetDebugger().GetCommandInterpreter().GetCurrentSourceDir();
1321       if (!source_dir) {
1322         result.AppendError("command script import -c can only be specified "
1323                            "from a command file");
1324         return false;
1325       }
1326     }
1327 
1328     for (auto &entry : command.entries()) {
1329       Status error;
1330 
1331       LoadScriptOptions options;
1332       options.SetInitSession(true);
1333       options.SetSilent(m_options.silent);
1334 
1335       // FIXME: this is necessary because CommandObject::CheckRequirements()
1336       // assumes that commands won't ever be recursively invoked, but it's
1337       // actually possible to craft a Python script that does other "command
1338       // script imports" in __lldb_init_module the real fix is to have
1339       // recursive commands possible with a CommandInvocation object separate
1340       // from the CommandObject itself, so that recursive command invocations
1341       // won't stomp on each other (wrt to execution contents, options, and
1342       // more)
1343       m_exe_ctx.Clear();
1344       if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule(
1345               entry.c_str(), options, error, /*module_sp=*/nullptr,
1346               source_dir)) {
1347         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1348       } else {
1349         result.AppendErrorWithFormat("module importing failed: %s",
1350                                      error.AsCString());
1351       }
1352     }
1353 
1354     return result.Succeeded();
1355   }
1356 
1357   CommandOptions m_options;
1358 };
1359 
1360 #define LLDB_OPTIONS_script_add
1361 #include "CommandOptions.inc"
1362 
1363 class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1364                                        public IOHandlerDelegateMultiline {
1365 public:
1366   CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1367       : CommandObjectParsed(interpreter, "command script add",
1368                             "Add a scripted function as an LLDB command.",
1369                             "Add a scripted function as an lldb command. "
1370                             "If you provide a single argument, the command "
1371                             "will be added at the root level of the command "
1372                             "hierarchy.  If there are more arguments they "
1373                             "must be a path to a user-added container "
1374                             "command, and the last element will be the new "
1375                             "command name."),
1376         IOHandlerDelegateMultiline("DONE") {
1377     CommandArgumentEntry arg1;
1378     CommandArgumentData cmd_arg;
1379 
1380     // This is one or more command names, which form the path to the command
1381     // you want to add.
1382     cmd_arg.arg_type = eArgTypeCommand;
1383     cmd_arg.arg_repetition = eArgRepeatPlus;
1384 
1385     // There is only one variant this argument could be; put it into the
1386     // argument entry.
1387     arg1.push_back(cmd_arg);
1388 
1389     // Push the data for the first argument into the m_arguments vector.
1390     m_arguments.push_back(arg1);
1391   }
1392 
1393   ~CommandObjectCommandsScriptAdd() override = default;
1394 
1395   Options *GetOptions() override { return &m_options; }
1396 
1397   void
1398   HandleArgumentCompletion(CompletionRequest &request,
1399                            OptionElementVector &opt_element_vector) override {
1400     CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
1401                                                       opt_element_vector);
1402   }
1403 
1404 protected:
1405   class CommandOptions : public Options {
1406   public:
1407     CommandOptions() = default;
1408 
1409     ~CommandOptions() override = default;
1410 
1411     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1412                           ExecutionContext *execution_context) override {
1413       Status error;
1414       const int short_option = m_getopt_table[option_idx].val;
1415 
1416       switch (short_option) {
1417       case 'f':
1418         if (!option_arg.empty())
1419           m_funct_name = std::string(option_arg);
1420         break;
1421       case 'c':
1422         if (!option_arg.empty())
1423           m_class_name = std::string(option_arg);
1424         break;
1425       case 'h':
1426         if (!option_arg.empty())
1427           m_short_help = std::string(option_arg);
1428         break;
1429       case 'o':
1430         m_overwrite_lazy = eLazyBoolYes;
1431         break;
1432       case 's':
1433         m_synchronicity =
1434             (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum(
1435                 option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
1436         if (!error.Success())
1437           error.SetErrorStringWithFormat(
1438               "unrecognized value for synchronicity '%s'",
1439               option_arg.str().c_str());
1440         break;
1441       default:
1442         llvm_unreachable("Unimplemented option");
1443       }
1444 
1445       return error;
1446     }
1447 
1448     void OptionParsingStarting(ExecutionContext *execution_context) override {
1449       m_class_name.clear();
1450       m_funct_name.clear();
1451       m_short_help.clear();
1452       m_overwrite_lazy = eLazyBoolCalculate;
1453       m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1454     }
1455 
1456     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1457       return llvm::makeArrayRef(g_script_add_options);
1458     }
1459 
1460     // Instance variables to hold the values for command options.
1461 
1462     std::string m_class_name;
1463     std::string m_funct_name;
1464     std::string m_short_help;
1465     LazyBool m_overwrite_lazy = eLazyBoolCalculate;
1466     ScriptedCommandSynchronicity m_synchronicity =
1467         eScriptedCommandSynchronicitySynchronous;
1468   };
1469 
1470   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
1471     StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
1472     if (output_sp && interactive) {
1473       output_sp->PutCString(g_python_command_instructions);
1474       output_sp->Flush();
1475     }
1476   }
1477 
1478   void IOHandlerInputComplete(IOHandler &io_handler,
1479                               std::string &data) override {
1480     StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
1481 
1482     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1483     if (interpreter) {
1484       StringList lines;
1485       lines.SplitIntoLines(data);
1486       if (lines.GetSize() > 0) {
1487         std::string funct_name_str;
1488         if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1489           if (funct_name_str.empty()) {
1490             error_sp->Printf("error: unable to obtain a function name, didn't "
1491                              "add python command.\n");
1492             error_sp->Flush();
1493           } else {
1494             // everything should be fine now, let's add this alias
1495 
1496             CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
1497                 m_interpreter, m_cmd_name, funct_name_str, m_short_help,
1498                 m_synchronicity));
1499             if (!m_container) {
1500               Status error = m_interpreter.AddUserCommand(
1501                   m_cmd_name, command_obj_sp, m_overwrite);
1502               if (error.Fail()) {
1503                 error_sp->Printf("error: unable to add selected command: '%s'",
1504                                  error.AsCString());
1505                 error_sp->Flush();
1506               }
1507             } else {
1508               llvm::Error llvm_error = m_container->LoadUserSubcommand(
1509                   m_cmd_name, command_obj_sp, m_overwrite);
1510               if (llvm_error) {
1511                 error_sp->Printf("error: unable to add selected command: '%s'",
1512                                llvm::toString(std::move(llvm_error)).c_str());
1513                 error_sp->Flush();
1514               }
1515             }
1516           }
1517         } else {
1518           error_sp->Printf(
1519               "error: unable to create function, didn't add python command\n");
1520           error_sp->Flush();
1521         }
1522       } else {
1523         error_sp->Printf("error: empty function, didn't add python command\n");
1524         error_sp->Flush();
1525       }
1526     } else {
1527       error_sp->Printf(
1528           "error: script interpreter missing, didn't add python command\n");
1529       error_sp->Flush();
1530     }
1531 
1532     io_handler.SetIsDone(true);
1533   }
1534 
1535   bool DoExecute(Args &command, CommandReturnObject &result) override {
1536     if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) {
1537       result.AppendError("only scripting language supported for scripted "
1538                          "commands is currently Python");
1539       return false;
1540     }
1541 
1542     if (command.GetArgumentCount() == 0) {
1543       result.AppendError("'command script add' requires at least one argument");
1544       return false;
1545     }
1546     // Store the options in case we get multi-line input, also figure out the
1547     // default if not user supplied:
1548     switch (m_options.m_overwrite_lazy) {
1549       case eLazyBoolCalculate:
1550         m_overwrite = !GetDebugger().GetCommandInterpreter().GetRequireCommandOverwrite();
1551         break;
1552       case eLazyBoolYes:
1553         m_overwrite = true;
1554         break;
1555       case eLazyBoolNo:
1556         m_overwrite = false;
1557     }
1558 
1559     Status path_error;
1560     m_container = GetCommandInterpreter().VerifyUserMultiwordCmdPath(
1561         command, true, path_error);
1562 
1563     if (path_error.Fail()) {
1564       result.AppendErrorWithFormat("error in command path: %s",
1565                                    path_error.AsCString());
1566       return false;
1567     }
1568 
1569     if (!m_container) {
1570       // This is getting inserted into the root of the interpreter.
1571       m_cmd_name = std::string(command[0].ref());
1572     } else {
1573       size_t num_args = command.GetArgumentCount();
1574       m_cmd_name = std::string(command[num_args - 1].ref());
1575     }
1576 
1577     m_short_help.assign(m_options.m_short_help);
1578     m_synchronicity = m_options.m_synchronicity;
1579 
1580     // Handle the case where we prompt for the script code first:
1581     if (m_options.m_class_name.empty() && m_options.m_funct_name.empty()) {
1582       m_interpreter.GetPythonCommandsFromIOHandler("     ", // Prompt
1583                                                    *this);  // IOHandlerDelegate
1584       return result.Succeeded();
1585     }
1586 
1587     CommandObjectSP new_cmd_sp;
1588     if (m_options.m_class_name.empty()) {
1589       new_cmd_sp.reset(new CommandObjectPythonFunction(
1590           m_interpreter, m_cmd_name, m_options.m_funct_name,
1591           m_options.m_short_help, m_synchronicity));
1592     } else {
1593       ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1594       if (!interpreter) {
1595         result.AppendError("cannot find ScriptInterpreter");
1596         return false;
1597       }
1598 
1599       auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1600           m_options.m_class_name.c_str());
1601       if (!cmd_obj_sp) {
1602         result.AppendError("cannot create helper object");
1603         return false;
1604       }
1605 
1606       new_cmd_sp.reset(new CommandObjectScriptingObject(
1607           m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1608     }
1609 
1610     // Assume we're going to succeed...
1611     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1612     if (!m_container) {
1613       Status add_error =
1614           m_interpreter.AddUserCommand(m_cmd_name, new_cmd_sp, m_overwrite);
1615       if (add_error.Fail())
1616         result.AppendErrorWithFormat("cannot add command: %s",
1617                                      add_error.AsCString());
1618     } else {
1619       llvm::Error llvm_error =
1620           m_container->LoadUserSubcommand(m_cmd_name, new_cmd_sp, m_overwrite);
1621       if (llvm_error)
1622         result.AppendErrorWithFormat("cannot add command: %s",
1623                                      llvm::toString(std::move(llvm_error)).c_str());
1624     }
1625     return result.Succeeded();
1626   }
1627 
1628   CommandOptions m_options;
1629   std::string m_cmd_name;
1630   CommandObjectMultiword *m_container = nullptr;
1631   std::string m_short_help;
1632   bool m_overwrite = false;
1633   ScriptedCommandSynchronicity m_synchronicity =
1634       eScriptedCommandSynchronicitySynchronous;
1635 };
1636 
1637 // CommandObjectCommandsScriptList
1638 
1639 class CommandObjectCommandsScriptList : public CommandObjectParsed {
1640 public:
1641   CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1642       : CommandObjectParsed(interpreter, "command script list",
1643                             "List defined top-level scripted commands.",
1644                             nullptr) {}
1645 
1646   ~CommandObjectCommandsScriptList() override = default;
1647 
1648   bool DoExecute(Args &command, CommandReturnObject &result) override {
1649     m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1650 
1651     result.SetStatus(eReturnStatusSuccessFinishResult);
1652 
1653     return true;
1654   }
1655 };
1656 
1657 // CommandObjectCommandsScriptClear
1658 
1659 class CommandObjectCommandsScriptClear : public CommandObjectParsed {
1660 public:
1661   CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1662       : CommandObjectParsed(interpreter, "command script clear",
1663                             "Delete all scripted commands.", nullptr) {}
1664 
1665   ~CommandObjectCommandsScriptClear() override = default;
1666 
1667 protected:
1668   bool DoExecute(Args &command, CommandReturnObject &result) override {
1669     m_interpreter.RemoveAllUser();
1670 
1671     result.SetStatus(eReturnStatusSuccessFinishResult);
1672 
1673     return true;
1674   }
1675 };
1676 
1677 // CommandObjectCommandsScriptDelete
1678 
1679 class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
1680 public:
1681   CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1682       : CommandObjectParsed(
1683             interpreter, "command script delete",
1684             "Delete a scripted command by specifying the path to the command.",
1685             nullptr) {
1686     CommandArgumentEntry arg1;
1687     CommandArgumentData cmd_arg;
1688 
1689     // This is a list of command names forming the path to the command
1690     // to be deleted.
1691     cmd_arg.arg_type = eArgTypeCommand;
1692     cmd_arg.arg_repetition = eArgRepeatPlus;
1693 
1694     // There is only one variant this argument could be; put it into the
1695     // argument entry.
1696     arg1.push_back(cmd_arg);
1697 
1698     // Push the data for the first argument into the m_arguments vector.
1699     m_arguments.push_back(arg1);
1700   }
1701 
1702   ~CommandObjectCommandsScriptDelete() override = default;
1703 
1704   void
1705   HandleArgumentCompletion(CompletionRequest &request,
1706                            OptionElementVector &opt_element_vector) override {
1707     CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
1708                                                       opt_element_vector);
1709   }
1710 
1711 protected:
1712   bool DoExecute(Args &command, CommandReturnObject &result) override {
1713 
1714     llvm::StringRef root_cmd = command[0].ref();
1715     size_t num_args = command.GetArgumentCount();
1716 
1717     if (root_cmd.empty()) {
1718       result.AppendErrorWithFormat("empty root command name");
1719       return false;
1720     }
1721     if (!m_interpreter.HasUserCommands() &&
1722         !m_interpreter.HasUserMultiwordCommands()) {
1723       result.AppendErrorWithFormat("can only delete user defined commands, "
1724                                    "but no user defined commands found");
1725       return false;
1726     }
1727 
1728     CommandObjectSP cmd_sp = m_interpreter.GetCommandSPExact(root_cmd);
1729     if (!cmd_sp) {
1730       result.AppendErrorWithFormat("command '%s' not found.",
1731                                    command[0].c_str());
1732       return false;
1733     }
1734     if (!cmd_sp->IsUserCommand()) {
1735       result.AppendErrorWithFormat("command '%s' is not a user command.",
1736                                    command[0].c_str());
1737       return false;
1738     }
1739     if (cmd_sp->GetAsMultiwordCommand() && num_args == 1) {
1740       result.AppendErrorWithFormat("command '%s' is a multi-word command.\n "
1741                                    "Delete with \"command container delete\"",
1742                                    command[0].c_str());
1743       return false;
1744     }
1745 
1746     if (command.GetArgumentCount() == 1) {
1747       m_interpreter.RemoveUser(root_cmd);
1748       result.SetStatus(eReturnStatusSuccessFinishResult);
1749       return true;
1750     }
1751     // We're deleting a command from a multiword command.  Verify the command
1752     // path:
1753     Status error;
1754     CommandObjectMultiword *container =
1755         GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
1756                                                            error);
1757     if (error.Fail()) {
1758       result.AppendErrorWithFormat("could not resolve command path: %s",
1759                                    error.AsCString());
1760       return false;
1761     }
1762     if (!container) {
1763       // This means that command only had a leaf command, so the container is
1764       // the root.  That should have been handled above.
1765       result.AppendErrorWithFormat("could not find a container for '%s'",
1766                                    command[0].c_str());
1767       return false;
1768     }
1769     const char *leaf_cmd = command[num_args - 1].c_str();
1770     llvm::Error llvm_error = container->RemoveUserSubcommand(leaf_cmd,
1771                                             /* multiword not okay */ false);
1772     if (llvm_error) {
1773       result.AppendErrorWithFormat("could not delete command '%s': %s",
1774                                    leaf_cmd,
1775                                    llvm::toString(std::move(llvm_error)).c_str());
1776       return false;
1777     }
1778 
1779     Stream &out_stream = result.GetOutputStream();
1780 
1781     out_stream << "Deleted command:";
1782     for (size_t idx = 0; idx < num_args; idx++) {
1783       out_stream << ' ';
1784       out_stream << command[idx].c_str();
1785     }
1786     out_stream << '\n';
1787     result.SetStatus(eReturnStatusSuccessFinishResult);
1788     return true;
1789   }
1790 };
1791 
1792 #pragma mark CommandObjectMultiwordCommandsScript
1793 
1794 // CommandObjectMultiwordCommandsScript
1795 
1796 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
1797 public:
1798   CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1799       : CommandObjectMultiword(
1800             interpreter, "command script",
1801             "Commands for managing custom "
1802             "commands implemented by "
1803             "interpreter scripts.",
1804             "command script <subcommand> [<subcommand-options>]") {
1805     LoadSubCommand("add", CommandObjectSP(
1806                               new CommandObjectCommandsScriptAdd(interpreter)));
1807     LoadSubCommand(
1808         "delete",
1809         CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1810     LoadSubCommand(
1811         "clear",
1812         CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1813     LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1814                                interpreter)));
1815     LoadSubCommand(
1816         "import",
1817         CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1818   }
1819 
1820   ~CommandObjectMultiwordCommandsScript() override = default;
1821 };
1822 
1823 #pragma mark CommandObjectCommandContainer
1824 #define LLDB_OPTIONS_container_add
1825 #include "CommandOptions.inc"
1826 
1827 class CommandObjectCommandsContainerAdd : public CommandObjectParsed {
1828 public:
1829   CommandObjectCommandsContainerAdd(CommandInterpreter &interpreter)
1830       : CommandObjectParsed(
1831             interpreter, "command container add",
1832             "Add a container command to lldb.  Adding to built-"
1833             "in container commands is not allowed.",
1834             "command container add [[path1]...] container-name") {
1835     CommandArgumentEntry arg1;
1836     CommandArgumentData cmd_arg;
1837 
1838     // This is one or more command names, which form the path to the command
1839     // you want to add.
1840     cmd_arg.arg_type = eArgTypeCommand;
1841     cmd_arg.arg_repetition = eArgRepeatPlus;
1842 
1843     // There is only one variant this argument could be; put it into the
1844     // argument entry.
1845     arg1.push_back(cmd_arg);
1846 
1847     // Push the data for the first argument into the m_arguments vector.
1848     m_arguments.push_back(arg1);
1849   }
1850 
1851   ~CommandObjectCommandsContainerAdd() override = default;
1852 
1853   Options *GetOptions() override { return &m_options; }
1854 
1855   void
1856   HandleArgumentCompletion(CompletionRequest &request,
1857                            OptionElementVector &opt_element_vector) override {
1858     CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
1859                                                       opt_element_vector);
1860   }
1861 
1862 protected:
1863   class CommandOptions : public Options {
1864   public:
1865     CommandOptions() = default;
1866 
1867     ~CommandOptions() override = default;
1868 
1869     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1870                           ExecutionContext *execution_context) override {
1871       Status error;
1872       const int short_option = m_getopt_table[option_idx].val;
1873 
1874       switch (short_option) {
1875       case 'h':
1876         if (!option_arg.empty())
1877           m_short_help = std::string(option_arg);
1878         break;
1879       case 'o':
1880         m_overwrite = true;
1881         break;
1882       case 'H':
1883         if (!option_arg.empty())
1884           m_long_help = std::string(option_arg);
1885         break;
1886       default:
1887         llvm_unreachable("Unimplemented option");
1888       }
1889 
1890       return error;
1891     }
1892 
1893     void OptionParsingStarting(ExecutionContext *execution_context) override {
1894       m_short_help.clear();
1895       m_long_help.clear();
1896       m_overwrite = false;
1897     }
1898 
1899     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1900       return llvm::makeArrayRef(g_container_add_options);
1901     }
1902 
1903     // Instance variables to hold the values for command options.
1904 
1905     std::string m_short_help;
1906     std::string m_long_help;
1907     bool m_overwrite = false;
1908   };
1909   bool DoExecute(Args &command, CommandReturnObject &result) override {
1910     size_t num_args = command.GetArgumentCount();
1911 
1912     if (num_args == 0) {
1913       result.AppendError("no command was specified");
1914       return false;
1915     }
1916 
1917     if (num_args == 1) {
1918       // We're adding this as a root command, so use the interpreter.
1919       const char *cmd_name = command.GetArgumentAtIndex(0);
1920       auto cmd_sp = CommandObjectSP(new CommandObjectMultiword(
1921           GetCommandInterpreter(), cmd_name, m_options.m_short_help.c_str(),
1922           m_options.m_long_help.c_str()));
1923       cmd_sp->GetAsMultiwordCommand()->SetRemovable(true);
1924       Status add_error = GetCommandInterpreter().AddUserCommand(
1925           cmd_name, cmd_sp, m_options.m_overwrite);
1926       if (add_error.Fail()) {
1927         result.AppendErrorWithFormat("error adding command: %s",
1928                                      add_error.AsCString());
1929         return false;
1930       }
1931       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1932       return true;
1933     }
1934 
1935     // We're adding this to a subcommand, first find the subcommand:
1936     Status path_error;
1937     CommandObjectMultiword *add_to_me =
1938         GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
1939                                                            path_error);
1940 
1941     if (!add_to_me) {
1942       result.AppendErrorWithFormat("error adding command: %s",
1943                                    path_error.AsCString());
1944       return false;
1945     }
1946 
1947     const char *cmd_name = command.GetArgumentAtIndex(num_args - 1);
1948     auto cmd_sp = CommandObjectSP(new CommandObjectMultiword(
1949         GetCommandInterpreter(), cmd_name, m_options.m_short_help.c_str(),
1950         m_options.m_long_help.c_str()));
1951     llvm::Error llvm_error =
1952         add_to_me->LoadUserSubcommand(cmd_name, cmd_sp, m_options.m_overwrite);
1953     if (llvm_error) {
1954       result.AppendErrorWithFormat("error adding subcommand: %s",
1955                                    llvm::toString(std::move(llvm_error)).c_str());
1956       return false;
1957     }
1958 
1959     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1960     return true;
1961   }
1962 
1963 private:
1964   CommandOptions m_options;
1965 };
1966 
1967 #define LLDB_OPTIONS_multiword_delete
1968 #include "CommandOptions.inc"
1969 class CommandObjectCommandsContainerDelete : public CommandObjectParsed {
1970 public:
1971   CommandObjectCommandsContainerDelete(CommandInterpreter &interpreter)
1972       : CommandObjectParsed(
1973             interpreter, "command container delete",
1974             "Delete a container command previously added to "
1975             "lldb.",
1976             "command container delete [[path1] ...] container-cmd") {
1977     CommandArgumentEntry arg1;
1978     CommandArgumentData cmd_arg;
1979 
1980     // This is one or more command names, which form the path to the command
1981     // you want to add.
1982     cmd_arg.arg_type = eArgTypeCommand;
1983     cmd_arg.arg_repetition = eArgRepeatPlus;
1984 
1985     // There is only one variant this argument could be; put it into the
1986     // argument entry.
1987     arg1.push_back(cmd_arg);
1988 
1989     // Push the data for the first argument into the m_arguments vector.
1990     m_arguments.push_back(arg1);
1991   }
1992 
1993   ~CommandObjectCommandsContainerDelete() override = default;
1994 
1995   void
1996   HandleArgumentCompletion(CompletionRequest &request,
1997                            OptionElementVector &opt_element_vector) override {
1998     CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
1999                                                       opt_element_vector);
2000   }
2001 
2002 protected:
2003   bool DoExecute(Args &command, CommandReturnObject &result) override {
2004     size_t num_args = command.GetArgumentCount();
2005 
2006     if (num_args == 0) {
2007       result.AppendError("No command was specified.");
2008       return false;
2009     }
2010 
2011     if (num_args == 1) {
2012       // We're removing a root command, so we need to delete it from the
2013       // interpreter.
2014       const char *cmd_name = command.GetArgumentAtIndex(0);
2015       // Let's do a little more work here so we can do better error reporting.
2016       CommandInterpreter &interp = GetCommandInterpreter();
2017       CommandObjectSP cmd_sp = interp.GetCommandSPExact(cmd_name);
2018       if (!cmd_sp) {
2019         result.AppendErrorWithFormat("container command %s doesn't exist.",
2020                                      cmd_name);
2021         return false;
2022       }
2023       if (!cmd_sp->IsUserCommand()) {
2024         result.AppendErrorWithFormat(
2025             "container command %s is not a user command", cmd_name);
2026         return false;
2027       }
2028       if (!cmd_sp->GetAsMultiwordCommand()) {
2029         result.AppendErrorWithFormat("command %s is not a container command",
2030                                      cmd_name);
2031         return false;
2032       }
2033 
2034       bool did_remove = GetCommandInterpreter().RemoveUserMultiword(cmd_name);
2035       if (!did_remove) {
2036         result.AppendErrorWithFormat("error removing command %s.", cmd_name);
2037         return false;
2038       }
2039 
2040       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2041       return true;
2042     }
2043 
2044     // We're removing a subcommand, first find the subcommand's owner:
2045     Status path_error;
2046     CommandObjectMultiword *container =
2047         GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
2048                                                            path_error);
2049 
2050     if (!container) {
2051       result.AppendErrorWithFormat("error removing container command: %s",
2052                                    path_error.AsCString());
2053       return false;
2054     }
2055     const char *leaf = command.GetArgumentAtIndex(num_args - 1);
2056     llvm::Error llvm_error =
2057         container->RemoveUserSubcommand(leaf, /* multiword okay */ true);
2058     if (llvm_error) {
2059       result.AppendErrorWithFormat("error removing container command: %s",
2060                                    llvm::toString(std::move(llvm_error)).c_str());
2061       return false;
2062     }
2063     result.SetStatus(eReturnStatusSuccessFinishNoResult);
2064     return true;
2065   }
2066 };
2067 
2068 class CommandObjectCommandContainer : public CommandObjectMultiword {
2069 public:
2070   CommandObjectCommandContainer(CommandInterpreter &interpreter)
2071       : CommandObjectMultiword(
2072             interpreter, "command container",
2073             "Commands for adding container commands to lldb.  "
2074             "Container commands are containers for other commands.  You can "
2075             "add nested container commands by specifying a command path, "
2076             "but you can't add commands into the built-in command hierarchy.",
2077             "command container <subcommand> [<subcommand-options>]") {
2078     LoadSubCommand("add", CommandObjectSP(new CommandObjectCommandsContainerAdd(
2079                               interpreter)));
2080     LoadSubCommand(
2081         "delete",
2082         CommandObjectSP(new CommandObjectCommandsContainerDelete(interpreter)));
2083   }
2084 
2085   ~CommandObjectCommandContainer() override = default;
2086 };
2087 
2088 #pragma mark CommandObjectMultiwordCommands
2089 
2090 // CommandObjectMultiwordCommands
2091 
2092 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
2093     CommandInterpreter &interpreter)
2094     : CommandObjectMultiword(interpreter, "command",
2095                              "Commands for managing custom LLDB commands.",
2096                              "command <subcommand> [<subcommand-options>]") {
2097   LoadSubCommand("source",
2098                  CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
2099   LoadSubCommand("alias",
2100                  CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
2101   LoadSubCommand("unalias", CommandObjectSP(
2102                                 new CommandObjectCommandsUnalias(interpreter)));
2103   LoadSubCommand("delete",
2104                  CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
2105   LoadSubCommand("container", CommandObjectSP(new CommandObjectCommandContainer(
2106                                   interpreter)));
2107   LoadSubCommand(
2108       "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
2109   LoadSubCommand(
2110       "script",
2111       CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
2112 }
2113 
2114 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
2115