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   llvm::Optional<std::string> GetRepeatCommand(Args &current_command_args,
60                                                uint32_t index) override {
61     return std::string("");
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) {
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 = false;
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 = false;
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 = false;
1641   ScriptedCommandSynchronicity m_synchronicity =
1642       eScriptedCommandSynchronicitySynchronous;
1643 };
1644 
1645 // CommandObjectCommandsScriptList
1646 
1647 class CommandObjectCommandsScriptList : public CommandObjectParsed {
1648 public:
1649   CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1650       : CommandObjectParsed(interpreter, "command script list",
1651                             "List defined top-level scripted commands.",
1652                             nullptr) {}
1653 
1654   ~CommandObjectCommandsScriptList() override = default;
1655 
1656   bool DoExecute(Args &command, CommandReturnObject &result) override {
1657     if (command.GetArgumentCount() != 0) {
1658       result.AppendError("'command script list' doesn't take any arguments");
1659       return false;
1660     }
1661 
1662     m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1663 
1664     result.SetStatus(eReturnStatusSuccessFinishResult);
1665 
1666     return true;
1667   }
1668 };
1669 
1670 // CommandObjectCommandsScriptClear
1671 
1672 class CommandObjectCommandsScriptClear : public CommandObjectParsed {
1673 public:
1674   CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1675       : CommandObjectParsed(interpreter, "command script clear",
1676                             "Delete all scripted commands.", nullptr) {}
1677 
1678   ~CommandObjectCommandsScriptClear() override = default;
1679 
1680 protected:
1681   bool DoExecute(Args &command, CommandReturnObject &result) override {
1682     if (command.GetArgumentCount() != 0) {
1683       result.AppendError("'command script clear' doesn't take any arguments");
1684       return false;
1685     }
1686 
1687     m_interpreter.RemoveAllUser();
1688 
1689     result.SetStatus(eReturnStatusSuccessFinishResult);
1690 
1691     return true;
1692   }
1693 };
1694 
1695 // CommandObjectCommandsScriptDelete
1696 
1697 class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
1698 public:
1699   CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1700       : CommandObjectParsed(
1701             interpreter, "command script delete",
1702             "Delete a scripted command by specifying the path to the command.",
1703             nullptr) {
1704     CommandArgumentEntry arg1;
1705     CommandArgumentData cmd_arg;
1706 
1707     // This is a list of command names forming the path to the command
1708     // to be deleted.
1709     cmd_arg.arg_type = eArgTypeCommand;
1710     cmd_arg.arg_repetition = eArgRepeatPlus;
1711 
1712     // There is only one variant this argument could be; put it into the
1713     // argument entry.
1714     arg1.push_back(cmd_arg);
1715 
1716     // Push the data for the first argument into the m_arguments vector.
1717     m_arguments.push_back(arg1);
1718   }
1719 
1720   ~CommandObjectCommandsScriptDelete() override = default;
1721 
1722   void
1723   HandleArgumentCompletion(CompletionRequest &request,
1724                            OptionElementVector &opt_element_vector) override {
1725     CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
1726                                                       opt_element_vector);
1727   }
1728 
1729 protected:
1730   bool DoExecute(Args &command, CommandReturnObject &result) override {
1731 
1732     llvm::StringRef root_cmd = command[0].ref();
1733     size_t num_args = command.GetArgumentCount();
1734 
1735     if (root_cmd.empty()) {
1736       result.AppendErrorWithFormat("empty root command name");
1737       return false;
1738     }
1739     if (!m_interpreter.HasUserCommands() &&
1740         !m_interpreter.HasUserMultiwordCommands()) {
1741       result.AppendErrorWithFormat("can only delete user defined commands, "
1742                                    "but no user defined commands found");
1743       return false;
1744     }
1745 
1746     CommandObjectSP cmd_sp = m_interpreter.GetCommandSPExact(root_cmd);
1747     if (!cmd_sp) {
1748       result.AppendErrorWithFormat("command '%s' not found.",
1749                                    command[0].c_str());
1750       return false;
1751     }
1752     if (!cmd_sp->IsUserCommand()) {
1753       result.AppendErrorWithFormat("command '%s' is not a user command.",
1754                                    command[0].c_str());
1755       return false;
1756     }
1757     if (cmd_sp->GetAsMultiwordCommand() && num_args == 1) {
1758       result.AppendErrorWithFormat("command '%s' is a multi-word command.\n "
1759                                    "Delete with \"command container delete\"",
1760                                    command[0].c_str());
1761       return false;
1762     }
1763 
1764     if (command.GetArgumentCount() == 1) {
1765       m_interpreter.RemoveUser(root_cmd);
1766       result.SetStatus(eReturnStatusSuccessFinishResult);
1767       return true;
1768     }
1769     // We're deleting a command from a multiword command.  Verify the command
1770     // path:
1771     Status error;
1772     CommandObjectMultiword *container =
1773         GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
1774                                                            error);
1775     if (error.Fail()) {
1776       result.AppendErrorWithFormat("could not resolve command path: %s",
1777                                    error.AsCString());
1778       return false;
1779     }
1780     if (!container) {
1781       // This means that command only had a leaf command, so the container is
1782       // the root.  That should have been handled above.
1783       result.AppendErrorWithFormat("could not find a container for '%s'",
1784                                    command[0].c_str());
1785       return false;
1786     }
1787     const char *leaf_cmd = command[num_args - 1].c_str();
1788     llvm::Error llvm_error = container->RemoveUserSubcommand(leaf_cmd,
1789                                             /* multiword not okay */ false);
1790     if (llvm_error) {
1791       result.AppendErrorWithFormat("could not delete command '%s': %s",
1792                                    leaf_cmd,
1793                                    llvm::toString(std::move(llvm_error)).c_str());
1794       return false;
1795     }
1796 
1797     Stream &out_stream = result.GetOutputStream();
1798 
1799     out_stream << "Deleted command:";
1800     for (size_t idx = 0; idx < num_args; idx++) {
1801       out_stream << ' ';
1802       out_stream << command[idx].c_str();
1803     }
1804     out_stream << '\n';
1805     result.SetStatus(eReturnStatusSuccessFinishResult);
1806     return true;
1807   }
1808 };
1809 
1810 #pragma mark CommandObjectMultiwordCommandsScript
1811 
1812 // CommandObjectMultiwordCommandsScript
1813 
1814 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
1815 public:
1816   CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1817       : CommandObjectMultiword(
1818             interpreter, "command script",
1819             "Commands for managing custom "
1820             "commands implemented by "
1821             "interpreter scripts.",
1822             "command script <subcommand> [<subcommand-options>]") {
1823     LoadSubCommand("add", CommandObjectSP(
1824                               new CommandObjectCommandsScriptAdd(interpreter)));
1825     LoadSubCommand(
1826         "delete",
1827         CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1828     LoadSubCommand(
1829         "clear",
1830         CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1831     LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1832                                interpreter)));
1833     LoadSubCommand(
1834         "import",
1835         CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1836   }
1837 
1838   ~CommandObjectMultiwordCommandsScript() override = default;
1839 };
1840 
1841 #pragma mark CommandObjectCommandContainer
1842 #define LLDB_OPTIONS_container_add
1843 #include "CommandOptions.inc"
1844 
1845 class CommandObjectCommandsContainerAdd : public CommandObjectParsed {
1846 public:
1847   CommandObjectCommandsContainerAdd(CommandInterpreter &interpreter)
1848       : CommandObjectParsed(
1849             interpreter, "command container add",
1850             "Add a container command to lldb.  Adding to built-"
1851             "in container commands is not allowed.",
1852             "command container add [[path1]...] container-name") {
1853     CommandArgumentEntry arg1;
1854     CommandArgumentData cmd_arg;
1855 
1856     // This is one or more command names, which form the path to the command
1857     // you want to add.
1858     cmd_arg.arg_type = eArgTypeCommand;
1859     cmd_arg.arg_repetition = eArgRepeatPlus;
1860 
1861     // There is only one variant this argument could be; put it into the
1862     // argument entry.
1863     arg1.push_back(cmd_arg);
1864 
1865     // Push the data for the first argument into the m_arguments vector.
1866     m_arguments.push_back(arg1);
1867   }
1868 
1869   ~CommandObjectCommandsContainerAdd() override = default;
1870 
1871   Options *GetOptions() override { return &m_options; }
1872 
1873   void
1874   HandleArgumentCompletion(CompletionRequest &request,
1875                            OptionElementVector &opt_element_vector) override {
1876     CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
1877                                                       opt_element_vector);
1878   }
1879 
1880 protected:
1881   class CommandOptions : public Options {
1882   public:
1883     CommandOptions() {}
1884 
1885     ~CommandOptions() override = default;
1886 
1887     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1888                           ExecutionContext *execution_context) override {
1889       Status error;
1890       const int short_option = m_getopt_table[option_idx].val;
1891 
1892       switch (short_option) {
1893       case 'h':
1894         if (!option_arg.empty())
1895           m_short_help = std::string(option_arg);
1896         break;
1897       case 'o':
1898         m_overwrite = true;
1899         break;
1900       case 'H':
1901         if (!option_arg.empty())
1902           m_long_help = std::string(option_arg);
1903         break;
1904       default:
1905         llvm_unreachable("Unimplemented option");
1906       }
1907 
1908       return error;
1909     }
1910 
1911     void OptionParsingStarting(ExecutionContext *execution_context) override {
1912       m_short_help.clear();
1913       m_long_help.clear();
1914       m_overwrite = false;
1915     }
1916 
1917     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1918       return llvm::makeArrayRef(g_container_add_options);
1919     }
1920 
1921     // Instance variables to hold the values for command options.
1922 
1923     std::string m_short_help;
1924     std::string m_long_help;
1925     bool m_overwrite = false;
1926   };
1927   bool DoExecute(Args &command, CommandReturnObject &result) override {
1928     size_t num_args = command.GetArgumentCount();
1929 
1930     if (num_args == 0) {
1931       result.AppendError("no command was specified");
1932       return false;
1933     }
1934 
1935     if (num_args == 1) {
1936       // We're adding this as a root command, so use the interpreter.
1937       const char *cmd_name = command.GetArgumentAtIndex(0);
1938       auto cmd_sp = CommandObjectSP(new CommandObjectMultiword(
1939           GetCommandInterpreter(), cmd_name, m_options.m_short_help.c_str(),
1940           m_options.m_long_help.c_str()));
1941       cmd_sp->GetAsMultiwordCommand()->SetRemovable(true);
1942       Status add_error = GetCommandInterpreter().AddUserCommand(
1943           cmd_name, cmd_sp, m_options.m_overwrite);
1944       if (add_error.Fail()) {
1945         result.AppendErrorWithFormat("error adding command: %s",
1946                                      add_error.AsCString());
1947         return false;
1948       }
1949       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1950       return true;
1951     }
1952 
1953     // We're adding this to a subcommand, first find the subcommand:
1954     Status path_error;
1955     CommandObjectMultiword *add_to_me =
1956         GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
1957                                                            path_error);
1958 
1959     if (!add_to_me) {
1960       result.AppendErrorWithFormat("error adding command: %s",
1961                                    path_error.AsCString());
1962       return false;
1963     }
1964 
1965     const char *cmd_name = command.GetArgumentAtIndex(num_args - 1);
1966     auto cmd_sp = CommandObjectSP(new CommandObjectMultiword(
1967         GetCommandInterpreter(), cmd_name, m_options.m_short_help.c_str(),
1968         m_options.m_long_help.c_str()));
1969     llvm::Error llvm_error =
1970         add_to_me->LoadUserSubcommand(cmd_name, cmd_sp, m_options.m_overwrite);
1971     if (llvm_error) {
1972       result.AppendErrorWithFormat("error adding subcommand: %s",
1973                                    llvm::toString(std::move(llvm_error)).c_str());
1974       return false;
1975     }
1976 
1977     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1978     return true;
1979   }
1980 
1981 private:
1982   CommandOptions m_options;
1983 };
1984 
1985 #define LLDB_OPTIONS_multiword_delete
1986 #include "CommandOptions.inc"
1987 class CommandObjectCommandsContainerDelete : public CommandObjectParsed {
1988 public:
1989   CommandObjectCommandsContainerDelete(CommandInterpreter &interpreter)
1990       : CommandObjectParsed(
1991             interpreter, "command container delete",
1992             "Delete a container command previously added to "
1993             "lldb.",
1994             "command container delete [[path1] ...] container-cmd") {
1995     CommandArgumentEntry arg1;
1996     CommandArgumentData cmd_arg;
1997 
1998     // This is one or more command names, which form the path to the command
1999     // you want to add.
2000     cmd_arg.arg_type = eArgTypeCommand;
2001     cmd_arg.arg_repetition = eArgRepeatPlus;
2002 
2003     // There is only one variant this argument could be; put it into the
2004     // argument entry.
2005     arg1.push_back(cmd_arg);
2006 
2007     // Push the data for the first argument into the m_arguments vector.
2008     m_arguments.push_back(arg1);
2009   }
2010 
2011   ~CommandObjectCommandsContainerDelete() override = default;
2012 
2013   void
2014   HandleArgumentCompletion(CompletionRequest &request,
2015                            OptionElementVector &opt_element_vector) override {
2016     CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
2017                                                       opt_element_vector);
2018   }
2019 
2020 protected:
2021   bool DoExecute(Args &command, CommandReturnObject &result) override {
2022     size_t num_args = command.GetArgumentCount();
2023 
2024     if (num_args == 0) {
2025       result.AppendError("No command was specified.");
2026       return false;
2027     }
2028 
2029     if (num_args == 1) {
2030       // We're removing a root command, so we need to delete it from the
2031       // interpreter.
2032       const char *cmd_name = command.GetArgumentAtIndex(0);
2033       // Let's do a little more work here so we can do better error reporting.
2034       CommandInterpreter &interp = GetCommandInterpreter();
2035       CommandObjectSP cmd_sp = interp.GetCommandSPExact(cmd_name);
2036       if (!cmd_sp) {
2037         result.AppendErrorWithFormat("container command %s doesn't exist.",
2038                                      cmd_name);
2039         return false;
2040       }
2041       if (!cmd_sp->IsUserCommand()) {
2042         result.AppendErrorWithFormat(
2043             "container command %s is not a user command", cmd_name);
2044         return false;
2045       }
2046       if (!cmd_sp->GetAsMultiwordCommand()) {
2047         result.AppendErrorWithFormat("command %s is not a container command",
2048                                      cmd_name);
2049         return false;
2050       }
2051 
2052       bool did_remove = GetCommandInterpreter().RemoveUserMultiword(cmd_name);
2053       if (!did_remove) {
2054         result.AppendErrorWithFormat("error removing command %s.", cmd_name);
2055         return false;
2056       }
2057 
2058       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2059       return true;
2060     }
2061 
2062     // We're removing a subcommand, first find the subcommand's owner:
2063     Status path_error;
2064     CommandObjectMultiword *container =
2065         GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
2066                                                            path_error);
2067 
2068     if (!container) {
2069       result.AppendErrorWithFormat("error removing container command: %s",
2070                                    path_error.AsCString());
2071       return false;
2072     }
2073     const char *leaf = command.GetArgumentAtIndex(num_args - 1);
2074     llvm::Error llvm_error =
2075         container->RemoveUserSubcommand(leaf, /* multiword okay */ true);
2076     if (llvm_error) {
2077       result.AppendErrorWithFormat("error removing container command: %s",
2078                                    llvm::toString(std::move(llvm_error)).c_str());
2079       return false;
2080     }
2081     result.SetStatus(eReturnStatusSuccessFinishNoResult);
2082     return true;
2083   }
2084 };
2085 
2086 class CommandObjectCommandContainer : public CommandObjectMultiword {
2087 public:
2088   CommandObjectCommandContainer(CommandInterpreter &interpreter)
2089       : CommandObjectMultiword(
2090             interpreter, "command container",
2091             "Commands for adding container commands to lldb.  "
2092             "Container commands are containers for other commands.  You can"
2093             "add nested container commands by specifying a command path, but "
2094             "but you can't add commands into the built-in command hierarchy.",
2095             "command container <subcommand> [<subcommand-options>]") {
2096     LoadSubCommand("add", CommandObjectSP(new CommandObjectCommandsContainerAdd(
2097                               interpreter)));
2098     LoadSubCommand(
2099         "delete",
2100         CommandObjectSP(new CommandObjectCommandsContainerDelete(interpreter)));
2101   }
2102 
2103   ~CommandObjectCommandContainer() override = default;
2104 };
2105 
2106 #pragma mark CommandObjectMultiwordCommands
2107 
2108 // CommandObjectMultiwordCommands
2109 
2110 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
2111     CommandInterpreter &interpreter)
2112     : CommandObjectMultiword(interpreter, "command",
2113                              "Commands for managing custom LLDB commands.",
2114                              "command <subcommand> [<subcommand-options>]") {
2115   LoadSubCommand("source",
2116                  CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
2117   LoadSubCommand("alias",
2118                  CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
2119   LoadSubCommand("unalias", CommandObjectSP(
2120                                 new CommandObjectCommandsUnalias(interpreter)));
2121   LoadSubCommand("delete",
2122                  CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
2123   LoadSubCommand("container", CommandObjectSP(new CommandObjectCommandContainer(
2124                                   interpreter)));
2125   LoadSubCommand(
2126       "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
2127   LoadSubCommand(
2128       "script",
2129       CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
2130 }
2131 
2132 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
2133