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