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