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