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
29using namespace lldb;
30using namespace lldb_private;
31
32// CommandObjectCommandsSource
33
34#define LLDB_OPTIONS_source
35#include "CommandOptions.inc"
36
37class CommandObjectCommandsSource : public CommandObjectParsed {
38public:
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
75protected:
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  void 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;
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;
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;
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  }
190
191  CommandOptions m_options;
192};
193
194#pragma mark CommandObjectCommandsAlias
195// CommandObjectCommandsAlias
196
197#define LLDB_OPTIONS_alias
198#include "CommandOptions.inc"
199
200static 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, exe_ctx, result, internal_dict):\n";
204
205class CommandObjectCommandsAlias : public CommandObjectRaw {
206protected:
207  class CommandOptions : public OptionGroup {
208  public:
209    CommandOptions() = default;
210
211    ~CommandOptions() override = default;
212
213    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
214      return llvm::ArrayRef(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
254public:
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 \
266commands, multi-word commands, and commands that take particular options.  \
267Below 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 \
278breakpoint commands are two-word commands, the user would still need to \
279enter 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 \
288filled in at the time the alias is created, or specified as positional \
289arguments, to be filled in when the alias is invoked.  The following example \
290shows 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 \
297options already part of the alias.  So if the user wants to set a breakpoint \
298by file and line without explicitly having to use the -f and -l options, the \
299user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \
300for the actual arguments that will be passed when the alias command is used.  \
301The number in the placeholder refers to the position/order the actual value \
302occupies when the alias is used.  All the occurrences of '%1' in the alias \
303will be replaced with the first argument, all the occurrences of '%2' in the \
304alias will be replaced with the second argument, and so on.  This also allows \
305actual arguments to be used multiple times within an alias (see 'process \
306launch' example below)."
307        R"(
308
309)"
310        "Note: the positional arguments must substitute as whole words in the resultant \
311command, 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 \
320following 'bfl' and the actual line number value will be filled in with the second \
321argument.  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
327This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
328
329Another 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 \
338alias could be defined with that value directly in the alias as a constant, \
339rather 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
385protected:
386  void 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;
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;
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;
409    }
410
411    // Get the alias command.
412
413    auto alias_command = args[0].ref();
414    if (alias_command.starts_with("-")) {
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;
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;
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;
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;
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    } else if (!cmd_obj->WantsRawCommandString()) {
465      // Note that args was initialized with the original command, and has not
466      // been updated to this point. Therefore can we pass it to the version of
467      // Execute that does not need/expect raw input in the alias.
468      HandleAliasingNormalCommand(args, result);
469    } else {
470      HandleAliasingRawCommand(alias_command, raw_command_string, *cmd_obj,
471                               result);
472    }
473  }
474
475  bool HandleAliasingRawCommand(llvm::StringRef alias_command,
476                                llvm::StringRef raw_command_string,
477                                CommandObject &cmd_obj,
478                                CommandReturnObject &result) {
479    // Verify & handle any options/arguments passed to the alias command
480
481    OptionArgVectorSP option_arg_vector_sp =
482        OptionArgVectorSP(new OptionArgVector);
483
484    const bool include_aliases = true;
485    // Look up the command using command's name first.  This is to resolve
486    // aliases when you are making nested aliases.  But if you don't find
487    // it that way, then it wasn't an alias and we can just use the object
488    // we were passed in.
489    CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact(
490            cmd_obj.GetCommandName(), include_aliases);
491    if (!cmd_obj_sp)
492      cmd_obj_sp = cmd_obj.shared_from_this();
493
494    if (m_interpreter.AliasExists(alias_command) ||
495        m_interpreter.UserCommandExists(alias_command)) {
496      result.AppendWarningWithFormat(
497          "Overwriting existing definition for '%s'.\n",
498          alias_command.str().c_str());
499    }
500    if (CommandAlias *alias = m_interpreter.AddAlias(
501            alias_command, cmd_obj_sp, raw_command_string)) {
502      if (m_command_options.m_help.OptionWasSet())
503        alias->SetHelp(m_command_options.m_help.GetCurrentValue());
504      if (m_command_options.m_long_help.OptionWasSet())
505        alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
506      result.SetStatus(eReturnStatusSuccessFinishNoResult);
507    } else {
508      result.AppendError("Unable to create requested alias.\n");
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
617class CommandObjectCommandsUnalias : public CommandObjectParsed {
618public:
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
652protected:
653  void 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;
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;
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;
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;
695    }
696
697    result.SetStatus(eReturnStatusSuccessFinishNoResult);
698  }
699};
700
701#pragma mark CommandObjectCommandsDelete
702// CommandObjectCommandsDelete
703
704class CommandObjectCommandsDelete : public CommandObjectParsed {
705public:
706  CommandObjectCommandsDelete(CommandInterpreter &interpreter)
707      : CommandObjectParsed(
708            interpreter, "command delete",
709            "Delete one or more custom commands defined by 'command regex'.",
710            nullptr) {
711    CommandArgumentEntry arg;
712    CommandArgumentData alias_arg;
713
714    // Define the first (and only) variant of this arg.
715    alias_arg.arg_type = eArgTypeCommandName;
716    alias_arg.arg_repetition = eArgRepeatPlain;
717
718    // There is only one variant this argument could be; put it into the
719    // argument entry.
720    arg.push_back(alias_arg);
721
722    // Push the data for the first argument into the m_arguments vector.
723    m_arguments.push_back(arg);
724  }
725
726  ~CommandObjectCommandsDelete() override = default;
727
728  void
729  HandleArgumentCompletion(CompletionRequest &request,
730                           OptionElementVector &opt_element_vector) override {
731    if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
732      return;
733
734    for (const auto &ent : m_interpreter.GetCommands()) {
735      if (ent.second->IsRemovable())
736        request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp());
737    }
738  }
739
740protected:
741  void DoExecute(Args &args, CommandReturnObject &result) override {
742    CommandObject::CommandMap::iterator pos;
743
744    if (args.empty()) {
745      result.AppendErrorWithFormat("must call '%s' with one or more valid user "
746                                   "defined regular expression command names",
747                                   GetCommandName().str().c_str());
748      return;
749    }
750
751    auto command_name = args[0].ref();
752    if (!m_interpreter.CommandExists(command_name)) {
753      StreamString error_msg_stream;
754      const bool generate_upropos = true;
755      const bool generate_type_lookup = false;
756      CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
757          &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(),
758          generate_upropos, generate_type_lookup);
759      result.AppendError(error_msg_stream.GetString());
760      return;
761    }
762
763    if (!m_interpreter.RemoveCommand(command_name)) {
764      result.AppendErrorWithFormat(
765          "'%s' is a permanent debugger command and cannot be removed.\n",
766          args[0].c_str());
767      return;
768    }
769
770    result.SetStatus(eReturnStatusSuccessFinishNoResult);
771  }
772};
773
774// CommandObjectCommandsAddRegex
775
776#define LLDB_OPTIONS_regex
777#include "CommandOptions.inc"
778
779#pragma mark CommandObjectCommandsAddRegex
780
781class CommandObjectCommandsAddRegex : public CommandObjectParsed,
782                                      public IOHandlerDelegateMultiline {
783public:
784  CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
785      : CommandObjectParsed(
786            interpreter, "command regex",
787            "Define a custom command in terms of "
788            "existing commands by matching "
789            "regular expressions.",
790            "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
791        IOHandlerDelegateMultiline("",
792                                   IOHandlerDelegate::Completion::LLDBCommand) {
793    SetHelpLong(
794        R"(
795)"
796        "This command allows the user to create powerful regular expression commands \
797with substitutions. The regular expressions and substitutions are specified \
798using the regular expression substitution format of:"
799        R"(
800
801    s/<regex>/<subst>/
802
803)"
804        "<regex> is a regular expression that can use parenthesis to capture regular \
805expression input and substitute the captured matches in the output using %1 \
806for the first match, %2 for the second, and so on."
807        R"(
808
809)"
810        "The regular expressions can all be specified on the command line if more than \
811one argument is provided. If just the command name is provided on the command \
812line, then the regular expressions and substitutions can be entered on separate \
813lines, followed by an empty line to terminate the command definition."
814        R"(
815
816EXAMPLES
817
818)"
819        "The following example will define a regular expression command named 'f' that \
820will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
821a number follows 'f':"
822        R"(
823
824    (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
825    CommandArgumentData thread_arg{eArgTypeSEDStylePair, eArgRepeatOptional};
826    m_arguments.push_back({thread_arg});
827  }
828
829  ~CommandObjectCommandsAddRegex() override = default;
830
831protected:
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  void 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;
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(), 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));
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
914  Status AppendRegexSubstitution(const llvm::StringRef &regex_sed,
915                                 bool check_only) {
916    Status error;
917
918    if (!m_regex_cmd_up) {
919      error.SetErrorStringWithFormat(
920          "invalid regular expression command object for: '%.*s'",
921          (int)regex_sed.size(), regex_sed.data());
922      return error;
923    }
924
925    size_t regex_sed_size = regex_sed.size();
926
927    if (regex_sed_size <= 1) {
928      error.SetErrorStringWithFormat(
929          "regular expression substitution string is too short: '%.*s'",
930          (int)regex_sed.size(), regex_sed.data());
931      return error;
932    }
933
934    if (regex_sed[0] != 's') {
935      error.SetErrorStringWithFormat("regular expression substitution string "
936                                     "doesn't start with 's': '%.*s'",
937                                     (int)regex_sed.size(), regex_sed.data());
938      return error;
939    }
940    const size_t first_separator_char_pos = 1;
941    // use the char that follows 's' as the regex separator character so we can
942    // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
943    const char separator_char = regex_sed[first_separator_char_pos];
944    const size_t second_separator_char_pos =
945        regex_sed.find(separator_char, first_separator_char_pos + 1);
946
947    if (second_separator_char_pos == std::string::npos) {
948      error.SetErrorStringWithFormat(
949          "missing second '%c' separator char after '%.*s' in '%.*s'",
950          separator_char,
951          (int)(regex_sed.size() - first_separator_char_pos - 1),
952          regex_sed.data() + (first_separator_char_pos + 1),
953          (int)regex_sed.size(), regex_sed.data());
954      return error;
955    }
956
957    const size_t third_separator_char_pos =
958        regex_sed.find(separator_char, second_separator_char_pos + 1);
959
960    if (third_separator_char_pos == std::string::npos) {
961      error.SetErrorStringWithFormat(
962          "missing third '%c' separator char after '%.*s' in '%.*s'",
963          separator_char,
964          (int)(regex_sed.size() - second_separator_char_pos - 1),
965          regex_sed.data() + (second_separator_char_pos + 1),
966          (int)regex_sed.size(), regex_sed.data());
967      return error;
968    }
969
970    if (third_separator_char_pos != regex_sed_size - 1) {
971      // Make sure that everything that follows the last regex separator char
972      if (regex_sed.find_first_not_of("\t\n\v\f\r ",
973                                      third_separator_char_pos + 1) !=
974          std::string::npos) {
975        error.SetErrorStringWithFormat(
976            "extra data found after the '%.*s' regular expression substitution "
977            "string: '%.*s'",
978            (int)third_separator_char_pos + 1, regex_sed.data(),
979            (int)(regex_sed.size() - third_separator_char_pos - 1),
980            regex_sed.data() + (third_separator_char_pos + 1));
981        return error;
982      }
983    } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
984      error.SetErrorStringWithFormat(
985          "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
986          separator_char, separator_char, separator_char, (int)regex_sed.size(),
987          regex_sed.data());
988      return error;
989    } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
990      error.SetErrorStringWithFormat(
991          "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
992          separator_char, separator_char, separator_char, (int)regex_sed.size(),
993          regex_sed.data());
994      return error;
995    }
996
997    if (!check_only) {
998      std::string regex(std::string(regex_sed.substr(
999          first_separator_char_pos + 1,
1000          second_separator_char_pos - first_separator_char_pos - 1)));
1001      std::string subst(std::string(regex_sed.substr(
1002          second_separator_char_pos + 1,
1003          third_separator_char_pos - second_separator_char_pos - 1)));
1004      m_regex_cmd_up->AddRegexCommand(regex, subst);
1005    }
1006    return error;
1007  }
1008
1009  void AddRegexCommandToInterpreter() {
1010    if (m_regex_cmd_up) {
1011      if (m_regex_cmd_up->HasRegexEntries()) {
1012        CommandObjectSP cmd_sp(m_regex_cmd_up.release());
1013        m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1014      }
1015    }
1016  }
1017
1018private:
1019  std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_up;
1020
1021  class CommandOptions : public Options {
1022  public:
1023    CommandOptions() = default;
1024
1025    ~CommandOptions() override = default;
1026
1027    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1028                          ExecutionContext *execution_context) override {
1029      Status error;
1030      const int short_option = m_getopt_table[option_idx].val;
1031
1032      switch (short_option) {
1033      case 'h':
1034        m_help.assign(std::string(option_arg));
1035        break;
1036      case 's':
1037        m_syntax.assign(std::string(option_arg));
1038        break;
1039      default:
1040        llvm_unreachable("Unimplemented option");
1041      }
1042
1043      return error;
1044    }
1045
1046    void OptionParsingStarting(ExecutionContext *execution_context) override {
1047      m_help.clear();
1048      m_syntax.clear();
1049    }
1050
1051    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1052      return llvm::ArrayRef(g_regex_options);
1053    }
1054
1055    llvm::StringRef GetHelp() { return m_help; }
1056
1057    llvm::StringRef GetSyntax() { return m_syntax; }
1058
1059  protected:
1060    // Instance variables to hold the values for command options.
1061
1062    std::string m_help;
1063    std::string m_syntax;
1064  };
1065
1066  Options *GetOptions() override { return &m_options; }
1067
1068  CommandOptions m_options;
1069};
1070
1071class CommandObjectPythonFunction : public CommandObjectRaw {
1072public:
1073  CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
1074                              std::string funct, std::string help,
1075                              ScriptedCommandSynchronicity synch,
1076                              CompletionType completion_type)
1077      : CommandObjectRaw(interpreter, name), m_function_name(funct),
1078        m_synchro(synch), m_completion_type(completion_type) {
1079    if (!help.empty())
1080      SetHelp(help);
1081    else {
1082      StreamString stream;
1083      stream.Printf("For more information run 'help %s'", name.c_str());
1084      SetHelp(stream.GetString());
1085    }
1086  }
1087
1088  ~CommandObjectPythonFunction() override = default;
1089
1090  bool IsRemovable() const override { return true; }
1091
1092  const std::string &GetFunctionName() { return m_function_name; }
1093
1094  ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1095
1096  llvm::StringRef GetHelpLong() override {
1097    if (m_fetched_help_long)
1098      return CommandObjectRaw::GetHelpLong();
1099
1100    ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1101    if (!scripter)
1102      return CommandObjectRaw::GetHelpLong();
1103
1104    std::string docstring;
1105    m_fetched_help_long =
1106        scripter->GetDocumentationForItem(m_function_name.c_str(), docstring);
1107    if (!docstring.empty())
1108      SetHelpLong(docstring);
1109    return CommandObjectRaw::GetHelpLong();
1110  }
1111
1112  void
1113  HandleArgumentCompletion(CompletionRequest &request,
1114                           OptionElementVector &opt_element_vector) override {
1115    lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1116        GetCommandInterpreter(), m_completion_type, request, nullptr);
1117  }
1118
1119  bool WantsCompletion() override { return true; }
1120
1121protected:
1122  void DoExecute(llvm::StringRef raw_command_line,
1123                 CommandReturnObject &result) override {
1124    ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1125
1126    Status error;
1127
1128    result.SetStatus(eReturnStatusInvalid);
1129
1130    if (!scripter || !scripter->RunScriptBasedCommand(
1131                         m_function_name.c_str(), raw_command_line, m_synchro,
1132                         result, error, m_exe_ctx)) {
1133      result.AppendError(error.AsCString());
1134    } else {
1135      // Don't change the status if the command already set it...
1136      if (result.GetStatus() == eReturnStatusInvalid) {
1137        if (result.GetOutputData().empty())
1138          result.SetStatus(eReturnStatusSuccessFinishNoResult);
1139        else
1140          result.SetStatus(eReturnStatusSuccessFinishResult);
1141      }
1142    }
1143  }
1144
1145private:
1146  std::string m_function_name;
1147  ScriptedCommandSynchronicity m_synchro;
1148  bool m_fetched_help_long = false;
1149  CompletionType m_completion_type = eNoCompletion;
1150};
1151
1152class CommandObjectScriptingObject : public CommandObjectRaw {
1153public:
1154  CommandObjectScriptingObject(CommandInterpreter &interpreter,
1155                               std::string name,
1156                               StructuredData::GenericSP cmd_obj_sp,
1157                               ScriptedCommandSynchronicity synch,
1158                               CompletionType completion_type)
1159      : CommandObjectRaw(interpreter, name), m_cmd_obj_sp(cmd_obj_sp),
1160        m_synchro(synch), m_fetched_help_short(false),
1161        m_fetched_help_long(false), m_completion_type(completion_type) {
1162    StreamString stream;
1163    stream.Printf("For more information run 'help %s'", name.c_str());
1164    SetHelp(stream.GetString());
1165    if (ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter())
1166      GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
1167  }
1168
1169  ~CommandObjectScriptingObject() override = default;
1170
1171  void
1172  HandleArgumentCompletion(CompletionRequest &request,
1173                           OptionElementVector &opt_element_vector) override {
1174    lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1175        GetCommandInterpreter(), m_completion_type, request, nullptr);
1176  }
1177
1178  bool WantsCompletion() override { return true; }
1179
1180  bool IsRemovable() const override { return true; }
1181
1182  ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1183
1184  llvm::StringRef GetHelp() override {
1185    if (m_fetched_help_short)
1186      return CommandObjectRaw::GetHelp();
1187    ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1188    if (!scripter)
1189      return CommandObjectRaw::GetHelp();
1190    std::string docstring;
1191    m_fetched_help_short =
1192        scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
1193    if (!docstring.empty())
1194      SetHelp(docstring);
1195
1196    return CommandObjectRaw::GetHelp();
1197  }
1198
1199  llvm::StringRef GetHelpLong() override {
1200    if (m_fetched_help_long)
1201      return CommandObjectRaw::GetHelpLong();
1202
1203    ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1204    if (!scripter)
1205      return CommandObjectRaw::GetHelpLong();
1206
1207    std::string docstring;
1208    m_fetched_help_long =
1209        scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
1210    if (!docstring.empty())
1211      SetHelpLong(docstring);
1212    return CommandObjectRaw::GetHelpLong();
1213  }
1214
1215protected:
1216  void DoExecute(llvm::StringRef raw_command_line,
1217                 CommandReturnObject &result) override {
1218    ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1219
1220    Status error;
1221
1222    result.SetStatus(eReturnStatusInvalid);
1223
1224    if (!scripter ||
1225        !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1226                                         m_synchro, result, error, m_exe_ctx)) {
1227      result.AppendError(error.AsCString());
1228    } else {
1229      // Don't change the status if the command already set it...
1230      if (result.GetStatus() == eReturnStatusInvalid) {
1231        if (result.GetOutputData().empty())
1232          result.SetStatus(eReturnStatusSuccessFinishNoResult);
1233        else
1234          result.SetStatus(eReturnStatusSuccessFinishResult);
1235      }
1236    }
1237  }
1238
1239private:
1240  StructuredData::GenericSP m_cmd_obj_sp;
1241  ScriptedCommandSynchronicity m_synchro;
1242  bool m_fetched_help_short : 1;
1243  bool m_fetched_help_long : 1;
1244  CompletionType m_completion_type = eNoCompletion;
1245};
1246
1247// CommandObjectCommandsScriptImport
1248#define LLDB_OPTIONS_script_import
1249#include "CommandOptions.inc"
1250
1251class CommandObjectCommandsScriptImport : public CommandObjectParsed {
1252public:
1253  CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1254      : CommandObjectParsed(interpreter, "command script import",
1255                            "Import a scripting module in LLDB.", nullptr) {
1256    CommandArgumentEntry arg1;
1257    CommandArgumentData cmd_arg;
1258
1259    // Define the first (and only) variant of this arg.
1260    cmd_arg.arg_type = eArgTypeFilename;
1261    cmd_arg.arg_repetition = eArgRepeatPlus;
1262
1263    // There is only one variant this argument could be; put it into the
1264    // argument entry.
1265    arg1.push_back(cmd_arg);
1266
1267    // Push the data for the first argument into the m_arguments vector.
1268    m_arguments.push_back(arg1);
1269  }
1270
1271  ~CommandObjectCommandsScriptImport() override = default;
1272
1273  void
1274  HandleArgumentCompletion(CompletionRequest &request,
1275                           OptionElementVector &opt_element_vector) override {
1276    lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1277        GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
1278  }
1279
1280  Options *GetOptions() override { return &m_options; }
1281
1282protected:
1283  class CommandOptions : public Options {
1284  public:
1285    CommandOptions() = default;
1286
1287    ~CommandOptions() override = default;
1288
1289    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1290                          ExecutionContext *execution_context) override {
1291      Status error;
1292      const int short_option = m_getopt_table[option_idx].val;
1293
1294      switch (short_option) {
1295      case 'r':
1296        // NO-OP
1297        break;
1298      case 'c':
1299        relative_to_command_file = true;
1300        break;
1301      case 's':
1302        silent = true;
1303        break;
1304      default:
1305        llvm_unreachable("Unimplemented option");
1306      }
1307
1308      return error;
1309    }
1310
1311    void OptionParsingStarting(ExecutionContext *execution_context) override {
1312      relative_to_command_file = false;
1313    }
1314
1315    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1316      return llvm::ArrayRef(g_script_import_options);
1317    }
1318    bool relative_to_command_file = false;
1319    bool silent = false;
1320  };
1321
1322  void DoExecute(Args &command, CommandReturnObject &result) override {
1323    if (command.empty()) {
1324      result.AppendError("command script import needs one or more arguments");
1325      return;
1326    }
1327
1328    FileSpec source_dir = {};
1329    if (m_options.relative_to_command_file) {
1330      source_dir = GetDebugger().GetCommandInterpreter().GetCurrentSourceDir();
1331      if (!source_dir) {
1332        result.AppendError("command script import -c can only be specified "
1333                           "from a command file");
1334        return;
1335      }
1336    }
1337
1338    for (auto &entry : command.entries()) {
1339      Status error;
1340
1341      LoadScriptOptions options;
1342      options.SetInitSession(true);
1343      options.SetSilent(m_options.silent);
1344
1345      // FIXME: this is necessary because CommandObject::CheckRequirements()
1346      // assumes that commands won't ever be recursively invoked, but it's
1347      // actually possible to craft a Python script that does other "command
1348      // script imports" in __lldb_init_module the real fix is to have
1349      // recursive commands possible with a CommandInvocation object separate
1350      // from the CommandObject itself, so that recursive command invocations
1351      // won't stomp on each other (wrt to execution contents, options, and
1352      // more)
1353      m_exe_ctx.Clear();
1354      if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule(
1355              entry.c_str(), options, error, /*module_sp=*/nullptr,
1356              source_dir)) {
1357        result.SetStatus(eReturnStatusSuccessFinishNoResult);
1358      } else {
1359        result.AppendErrorWithFormat("module importing failed: %s",
1360                                     error.AsCString());
1361      }
1362    }
1363  }
1364
1365  CommandOptions m_options;
1366};
1367
1368#define LLDB_OPTIONS_script_add
1369#include "CommandOptions.inc"
1370
1371class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1372                                       public IOHandlerDelegateMultiline {
1373public:
1374  CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1375      : CommandObjectParsed(interpreter, "command script add",
1376                            "Add a scripted function as an LLDB command.",
1377                            "Add a scripted function as an lldb command. "
1378                            "If you provide a single argument, the command "
1379                            "will be added at the root level of the command "
1380                            "hierarchy.  If there are more arguments they "
1381                            "must be a path to a user-added container "
1382                            "command, and the last element will be the new "
1383                            "command name."),
1384        IOHandlerDelegateMultiline("DONE") {
1385    CommandArgumentEntry arg1;
1386    CommandArgumentData cmd_arg;
1387
1388    // This is one or more command names, which form the path to the command
1389    // you want to add.
1390    cmd_arg.arg_type = eArgTypeCommand;
1391    cmd_arg.arg_repetition = eArgRepeatPlus;
1392
1393    // There is only one variant this argument could be; put it into the
1394    // argument entry.
1395    arg1.push_back(cmd_arg);
1396
1397    // Push the data for the first argument into the m_arguments vector.
1398    m_arguments.push_back(arg1);
1399  }
1400
1401  ~CommandObjectCommandsScriptAdd() override = default;
1402
1403  Options *GetOptions() override { return &m_options; }
1404
1405  void
1406  HandleArgumentCompletion(CompletionRequest &request,
1407                           OptionElementVector &opt_element_vector) override {
1408    CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
1409                                                      opt_element_vector);
1410  }
1411
1412protected:
1413  class CommandOptions : public Options {
1414  public:
1415    CommandOptions() = default;
1416
1417    ~CommandOptions() override = default;
1418
1419    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1420                          ExecutionContext *execution_context) override {
1421      Status error;
1422      const int short_option = m_getopt_table[option_idx].val;
1423
1424      switch (short_option) {
1425      case 'f':
1426        if (!option_arg.empty())
1427          m_funct_name = std::string(option_arg);
1428        break;
1429      case 'c':
1430        if (!option_arg.empty())
1431          m_class_name = std::string(option_arg);
1432        break;
1433      case 'h':
1434        if (!option_arg.empty())
1435          m_short_help = std::string(option_arg);
1436        break;
1437      case 'o':
1438        m_overwrite_lazy = eLazyBoolYes;
1439        break;
1440      case 's':
1441        m_synchronicity =
1442            (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum(
1443                option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
1444        if (!error.Success())
1445          error.SetErrorStringWithFormat(
1446              "unrecognized value for synchronicity '%s'",
1447              option_arg.str().c_str());
1448        break;
1449      case 'C': {
1450        Status error;
1451        OptionDefinition definition = GetDefinitions()[option_idx];
1452        lldb::CompletionType completion_type =
1453            static_cast<lldb::CompletionType>(OptionArgParser::ToOptionEnum(
1454                option_arg, definition.enum_values, eNoCompletion, error));
1455        if (!error.Success())
1456          error.SetErrorStringWithFormat(
1457              "unrecognized value for command completion type '%s'",
1458              option_arg.str().c_str());
1459        m_completion_type = completion_type;
1460      } break;
1461      default:
1462        llvm_unreachable("Unimplemented option");
1463      }
1464
1465      return error;
1466    }
1467
1468    void OptionParsingStarting(ExecutionContext *execution_context) override {
1469      m_class_name.clear();
1470      m_funct_name.clear();
1471      m_short_help.clear();
1472      m_completion_type = eNoCompletion;
1473      m_overwrite_lazy = eLazyBoolCalculate;
1474      m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1475    }
1476
1477    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1478      return llvm::ArrayRef(g_script_add_options);
1479    }
1480
1481    // Instance variables to hold the values for command options.
1482
1483    std::string m_class_name;
1484    std::string m_funct_name;
1485    std::string m_short_help;
1486    LazyBool m_overwrite_lazy = eLazyBoolCalculate;
1487    ScriptedCommandSynchronicity m_synchronicity =
1488        eScriptedCommandSynchronicitySynchronous;
1489    CompletionType m_completion_type = eNoCompletion;
1490  };
1491
1492  void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
1493    StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
1494    if (output_sp && interactive) {
1495      output_sp->PutCString(g_python_command_instructions);
1496      output_sp->Flush();
1497    }
1498  }
1499
1500  void IOHandlerInputComplete(IOHandler &io_handler,
1501                              std::string &data) override {
1502    StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
1503
1504    ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1505    if (interpreter) {
1506      StringList lines;
1507      lines.SplitIntoLines(data);
1508      if (lines.GetSize() > 0) {
1509        std::string funct_name_str;
1510        if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1511          if (funct_name_str.empty()) {
1512            error_sp->Printf("error: unable to obtain a function name, didn't "
1513                             "add python command.\n");
1514            error_sp->Flush();
1515          } else {
1516            // everything should be fine now, let's add this alias
1517
1518            CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
1519                m_interpreter, m_cmd_name, funct_name_str, m_short_help,
1520                m_synchronicity, m_completion_type));
1521            if (!m_container) {
1522              Status error = m_interpreter.AddUserCommand(
1523                  m_cmd_name, command_obj_sp, m_overwrite);
1524              if (error.Fail()) {
1525                error_sp->Printf("error: unable to add selected command: '%s'",
1526                                 error.AsCString());
1527                error_sp->Flush();
1528              }
1529            } else {
1530              llvm::Error llvm_error = m_container->LoadUserSubcommand(
1531                  m_cmd_name, command_obj_sp, m_overwrite);
1532              if (llvm_error) {
1533                error_sp->Printf("error: unable to add selected command: '%s'",
1534                               llvm::toString(std::move(llvm_error)).c_str());
1535                error_sp->Flush();
1536              }
1537            }
1538          }
1539        } else {
1540          error_sp->Printf(
1541              "error: unable to create function, didn't add python command\n");
1542          error_sp->Flush();
1543        }
1544      } else {
1545        error_sp->Printf("error: empty function, didn't add python command\n");
1546        error_sp->Flush();
1547      }
1548    } else {
1549      error_sp->Printf(
1550          "error: script interpreter missing, didn't add python command\n");
1551      error_sp->Flush();
1552    }
1553
1554    io_handler.SetIsDone(true);
1555  }
1556
1557  void DoExecute(Args &command, CommandReturnObject &result) override {
1558    if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) {
1559      result.AppendError("only scripting language supported for scripted "
1560                         "commands is currently Python");
1561      return;
1562    }
1563
1564    if (command.GetArgumentCount() == 0) {
1565      result.AppendError("'command script add' requires at least one argument");
1566      return;
1567    }
1568    // Store the options in case we get multi-line input, also figure out the
1569    // default if not user supplied:
1570    switch (m_options.m_overwrite_lazy) {
1571      case eLazyBoolCalculate:
1572        m_overwrite = !GetDebugger().GetCommandInterpreter().GetRequireCommandOverwrite();
1573        break;
1574      case eLazyBoolYes:
1575        m_overwrite = true;
1576        break;
1577      case eLazyBoolNo:
1578        m_overwrite = false;
1579    }
1580
1581    Status path_error;
1582    m_container = GetCommandInterpreter().VerifyUserMultiwordCmdPath(
1583        command, true, path_error);
1584
1585    if (path_error.Fail()) {
1586      result.AppendErrorWithFormat("error in command path: %s",
1587                                   path_error.AsCString());
1588      return;
1589    }
1590
1591    if (!m_container) {
1592      // This is getting inserted into the root of the interpreter.
1593      m_cmd_name = std::string(command[0].ref());
1594    } else {
1595      size_t num_args = command.GetArgumentCount();
1596      m_cmd_name = std::string(command[num_args - 1].ref());
1597    }
1598
1599    m_short_help.assign(m_options.m_short_help);
1600    m_synchronicity = m_options.m_synchronicity;
1601    m_completion_type = m_options.m_completion_type;
1602
1603    // Handle the case where we prompt for the script code first:
1604    if (m_options.m_class_name.empty() && m_options.m_funct_name.empty()) {
1605      m_interpreter.GetPythonCommandsFromIOHandler("     ", // Prompt
1606                                                   *this);  // IOHandlerDelegate
1607      return;
1608    }
1609
1610    CommandObjectSP new_cmd_sp;
1611    if (m_options.m_class_name.empty()) {
1612      new_cmd_sp.reset(new CommandObjectPythonFunction(
1613          m_interpreter, m_cmd_name, m_options.m_funct_name,
1614          m_options.m_short_help, m_synchronicity, m_completion_type));
1615    } else {
1616      ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1617      if (!interpreter) {
1618        result.AppendError("cannot find ScriptInterpreter");
1619        return;
1620      }
1621
1622      auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1623          m_options.m_class_name.c_str());
1624      if (!cmd_obj_sp) {
1625        result.AppendErrorWithFormatv("cannot create helper object for: "
1626                                      "'{0}'", m_options.m_class_name);
1627        return;
1628      }
1629
1630      new_cmd_sp.reset(new CommandObjectScriptingObject(
1631          m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity,
1632          m_completion_type));
1633    }
1634
1635    // Assume we're going to succeed...
1636    result.SetStatus(eReturnStatusSuccessFinishNoResult);
1637    if (!m_container) {
1638      Status add_error =
1639          m_interpreter.AddUserCommand(m_cmd_name, new_cmd_sp, m_overwrite);
1640      if (add_error.Fail())
1641        result.AppendErrorWithFormat("cannot add command: %s",
1642                                     add_error.AsCString());
1643    } else {
1644      llvm::Error llvm_error =
1645          m_container->LoadUserSubcommand(m_cmd_name, new_cmd_sp, m_overwrite);
1646      if (llvm_error)
1647        result.AppendErrorWithFormat("cannot add command: %s",
1648                                     llvm::toString(std::move(llvm_error)).c_str());
1649    }
1650  }
1651
1652  CommandOptions m_options;
1653  std::string m_cmd_name;
1654  CommandObjectMultiword *m_container = nullptr;
1655  std::string m_short_help;
1656  bool m_overwrite = false;
1657  ScriptedCommandSynchronicity m_synchronicity =
1658      eScriptedCommandSynchronicitySynchronous;
1659  CompletionType m_completion_type = eNoCompletion;
1660};
1661
1662// CommandObjectCommandsScriptList
1663
1664class CommandObjectCommandsScriptList : public CommandObjectParsed {
1665public:
1666  CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1667      : CommandObjectParsed(interpreter, "command script list",
1668                            "List defined top-level scripted commands.",
1669                            nullptr) {}
1670
1671  ~CommandObjectCommandsScriptList() override = default;
1672
1673  void DoExecute(Args &command, CommandReturnObject &result) override {
1674    m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1675
1676    result.SetStatus(eReturnStatusSuccessFinishResult);
1677  }
1678};
1679
1680// CommandObjectCommandsScriptClear
1681
1682class CommandObjectCommandsScriptClear : public CommandObjectParsed {
1683public:
1684  CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1685      : CommandObjectParsed(interpreter, "command script clear",
1686                            "Delete all scripted commands.", nullptr) {}
1687
1688  ~CommandObjectCommandsScriptClear() override = default;
1689
1690protected:
1691  void DoExecute(Args &command, CommandReturnObject &result) override {
1692    m_interpreter.RemoveAllUser();
1693
1694    result.SetStatus(eReturnStatusSuccessFinishResult);
1695  }
1696};
1697
1698// CommandObjectCommandsScriptDelete
1699
1700class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
1701public:
1702  CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1703      : CommandObjectParsed(
1704            interpreter, "command script delete",
1705            "Delete a scripted command by specifying the path to the command.",
1706            nullptr) {
1707    CommandArgumentEntry arg1;
1708    CommandArgumentData cmd_arg;
1709
1710    // This is a list of command names forming the path to the command
1711    // to be deleted.
1712    cmd_arg.arg_type = eArgTypeCommand;
1713    cmd_arg.arg_repetition = eArgRepeatPlus;
1714
1715    // There is only one variant this argument could be; put it into the
1716    // argument entry.
1717    arg1.push_back(cmd_arg);
1718
1719    // Push the data for the first argument into the m_arguments vector.
1720    m_arguments.push_back(arg1);
1721  }
1722
1723  ~CommandObjectCommandsScriptDelete() override = default;
1724
1725  void
1726  HandleArgumentCompletion(CompletionRequest &request,
1727                           OptionElementVector &opt_element_vector) override {
1728    lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs(
1729        m_interpreter, request, opt_element_vector);
1730  }
1731
1732protected:
1733  void DoExecute(Args &command, CommandReturnObject &result) override {
1734
1735    llvm::StringRef root_cmd = command[0].ref();
1736    size_t num_args = command.GetArgumentCount();
1737
1738    if (root_cmd.empty()) {
1739      result.AppendErrorWithFormat("empty root command name");
1740      return;
1741    }
1742    if (!m_interpreter.HasUserCommands() &&
1743        !m_interpreter.HasUserMultiwordCommands()) {
1744      result.AppendErrorWithFormat("can only delete user defined commands, "
1745                                   "but no user defined commands found");
1746      return;
1747    }
1748
1749    CommandObjectSP cmd_sp = m_interpreter.GetCommandSPExact(root_cmd);
1750    if (!cmd_sp) {
1751      result.AppendErrorWithFormat("command '%s' not found.",
1752                                   command[0].c_str());
1753      return;
1754    }
1755    if (!cmd_sp->IsUserCommand()) {
1756      result.AppendErrorWithFormat("command '%s' is not a user command.",
1757                                   command[0].c_str());
1758      return;
1759    }
1760    if (cmd_sp->GetAsMultiwordCommand() && num_args == 1) {
1761      result.AppendErrorWithFormat("command '%s' is a multi-word command.\n "
1762                                   "Delete with \"command container delete\"",
1763                                   command[0].c_str());
1764      return;
1765    }
1766
1767    if (command.GetArgumentCount() == 1) {
1768      m_interpreter.RemoveUser(root_cmd);
1769      result.SetStatus(eReturnStatusSuccessFinishResult);
1770      return;
1771    }
1772    // We're deleting a command from a multiword command.  Verify the command
1773    // path:
1774    Status error;
1775    CommandObjectMultiword *container =
1776        GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
1777                                                           error);
1778    if (error.Fail()) {
1779      result.AppendErrorWithFormat("could not resolve command path: %s",
1780                                   error.AsCString());
1781      return;
1782    }
1783    if (!container) {
1784      // This means that command only had a leaf command, so the container is
1785      // the root.  That should have been handled above.
1786      result.AppendErrorWithFormat("could not find a container for '%s'",
1787                                   command[0].c_str());
1788      return;
1789    }
1790    const char *leaf_cmd = command[num_args - 1].c_str();
1791    llvm::Error llvm_error = container->RemoveUserSubcommand(leaf_cmd,
1792                                            /* multiword not okay */ false);
1793    if (llvm_error) {
1794      result.AppendErrorWithFormat("could not delete command '%s': %s",
1795                                   leaf_cmd,
1796                                   llvm::toString(std::move(llvm_error)).c_str());
1797      return;
1798    }
1799
1800    Stream &out_stream = result.GetOutputStream();
1801
1802    out_stream << "Deleted command:";
1803    for (size_t idx = 0; idx < num_args; idx++) {
1804      out_stream << ' ';
1805      out_stream << command[idx].c_str();
1806    }
1807    out_stream << '\n';
1808    result.SetStatus(eReturnStatusSuccessFinishResult);
1809  }
1810};
1811
1812#pragma mark CommandObjectMultiwordCommandsScript
1813
1814// CommandObjectMultiwordCommandsScript
1815
1816class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
1817public:
1818  CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1819      : CommandObjectMultiword(
1820            interpreter, "command script",
1821            "Commands for managing custom "
1822            "commands implemented by "
1823            "interpreter scripts.",
1824            "command script <subcommand> [<subcommand-options>]") {
1825    LoadSubCommand("add", CommandObjectSP(
1826                              new CommandObjectCommandsScriptAdd(interpreter)));
1827    LoadSubCommand(
1828        "delete",
1829        CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1830    LoadSubCommand(
1831        "clear",
1832        CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1833    LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1834                               interpreter)));
1835    LoadSubCommand(
1836        "import",
1837        CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1838  }
1839
1840  ~CommandObjectMultiwordCommandsScript() override = default;
1841};
1842
1843#pragma mark CommandObjectCommandContainer
1844#define LLDB_OPTIONS_container_add
1845#include "CommandOptions.inc"
1846
1847class CommandObjectCommandsContainerAdd : public CommandObjectParsed {
1848public:
1849  CommandObjectCommandsContainerAdd(CommandInterpreter &interpreter)
1850      : CommandObjectParsed(
1851            interpreter, "command container add",
1852            "Add a container command to lldb.  Adding to built-"
1853            "in container commands is not allowed.",
1854            "command container add [[path1]...] container-name") {
1855    CommandArgumentEntry arg1;
1856    CommandArgumentData cmd_arg;
1857
1858    // This is one or more command names, which form the path to the command
1859    // you want to add.
1860    cmd_arg.arg_type = eArgTypeCommand;
1861    cmd_arg.arg_repetition = eArgRepeatPlus;
1862
1863    // There is only one variant this argument could be; put it into the
1864    // argument entry.
1865    arg1.push_back(cmd_arg);
1866
1867    // Push the data for the first argument into the m_arguments vector.
1868    m_arguments.push_back(arg1);
1869  }
1870
1871  ~CommandObjectCommandsContainerAdd() override = default;
1872
1873  Options *GetOptions() override { return &m_options; }
1874
1875  void
1876  HandleArgumentCompletion(CompletionRequest &request,
1877                           OptionElementVector &opt_element_vector) override {
1878    lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs(
1879        m_interpreter, request, opt_element_vector);
1880  }
1881
1882protected:
1883  class CommandOptions : public Options {
1884  public:
1885    CommandOptions() = default;
1886
1887    ~CommandOptions() override = default;
1888
1889    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1890                          ExecutionContext *execution_context) override {
1891      Status error;
1892      const int short_option = m_getopt_table[option_idx].val;
1893
1894      switch (short_option) {
1895      case 'h':
1896        if (!option_arg.empty())
1897          m_short_help = std::string(option_arg);
1898        break;
1899      case 'o':
1900        m_overwrite = true;
1901        break;
1902      case 'H':
1903        if (!option_arg.empty())
1904          m_long_help = std::string(option_arg);
1905        break;
1906      default:
1907        llvm_unreachable("Unimplemented option");
1908      }
1909
1910      return error;
1911    }
1912
1913    void OptionParsingStarting(ExecutionContext *execution_context) override {
1914      m_short_help.clear();
1915      m_long_help.clear();
1916      m_overwrite = false;
1917    }
1918
1919    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1920      return llvm::ArrayRef(g_container_add_options);
1921    }
1922
1923    // Instance variables to hold the values for command options.
1924
1925    std::string m_short_help;
1926    std::string m_long_help;
1927    bool m_overwrite = false;
1928  };
1929  void DoExecute(Args &command, CommandReturnObject &result) override {
1930    size_t num_args = command.GetArgumentCount();
1931
1932    if (num_args == 0) {
1933      result.AppendError("no command was specified");
1934      return;
1935    }
1936
1937    if (num_args == 1) {
1938      // We're adding this as a root command, so use the interpreter.
1939      const char *cmd_name = command.GetArgumentAtIndex(0);
1940      auto cmd_sp = CommandObjectSP(new CommandObjectMultiword(
1941          GetCommandInterpreter(), cmd_name, m_options.m_short_help.c_str(),
1942          m_options.m_long_help.c_str()));
1943      cmd_sp->GetAsMultiwordCommand()->SetRemovable(true);
1944      Status add_error = GetCommandInterpreter().AddUserCommand(
1945          cmd_name, cmd_sp, m_options.m_overwrite);
1946      if (add_error.Fail()) {
1947        result.AppendErrorWithFormat("error adding command: %s",
1948                                     add_error.AsCString());
1949        return;
1950      }
1951      result.SetStatus(eReturnStatusSuccessFinishNoResult);
1952      return;
1953    }
1954
1955    // We're adding this to a subcommand, first find the subcommand:
1956    Status path_error;
1957    CommandObjectMultiword *add_to_me =
1958        GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
1959                                                           path_error);
1960
1961    if (!add_to_me) {
1962      result.AppendErrorWithFormat("error adding command: %s",
1963                                   path_error.AsCString());
1964      return;
1965    }
1966
1967    const char *cmd_name = command.GetArgumentAtIndex(num_args - 1);
1968    auto cmd_sp = CommandObjectSP(new CommandObjectMultiword(
1969        GetCommandInterpreter(), cmd_name, m_options.m_short_help.c_str(),
1970        m_options.m_long_help.c_str()));
1971    llvm::Error llvm_error =
1972        add_to_me->LoadUserSubcommand(cmd_name, cmd_sp, m_options.m_overwrite);
1973    if (llvm_error) {
1974      result.AppendErrorWithFormat("error adding subcommand: %s",
1975                                   llvm::toString(std::move(llvm_error)).c_str());
1976      return;
1977    }
1978
1979    result.SetStatus(eReturnStatusSuccessFinishNoResult);
1980  }
1981
1982private:
1983  CommandOptions m_options;
1984};
1985
1986#define LLDB_OPTIONS_multiword_delete
1987#include "CommandOptions.inc"
1988class CommandObjectCommandsContainerDelete : public CommandObjectParsed {
1989public:
1990  CommandObjectCommandsContainerDelete(CommandInterpreter &interpreter)
1991      : CommandObjectParsed(
1992            interpreter, "command container delete",
1993            "Delete a container command previously added to "
1994            "lldb.",
1995            "command container delete [[path1] ...] container-cmd") {
1996    CommandArgumentEntry arg1;
1997    CommandArgumentData cmd_arg;
1998
1999    // This is one or more command names, which form the path to the command
2000    // you want to add.
2001    cmd_arg.arg_type = eArgTypeCommand;
2002    cmd_arg.arg_repetition = eArgRepeatPlus;
2003
2004    // There is only one variant this argument could be; put it into the
2005    // argument entry.
2006    arg1.push_back(cmd_arg);
2007
2008    // Push the data for the first argument into the m_arguments vector.
2009    m_arguments.push_back(arg1);
2010  }
2011
2012  ~CommandObjectCommandsContainerDelete() override = default;
2013
2014  void
2015  HandleArgumentCompletion(CompletionRequest &request,
2016                           OptionElementVector &opt_element_vector) override {
2017    lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs(
2018        m_interpreter, request, opt_element_vector);
2019  }
2020
2021protected:
2022  void DoExecute(Args &command, CommandReturnObject &result) override {
2023    size_t num_args = command.GetArgumentCount();
2024
2025    if (num_args == 0) {
2026      result.AppendError("No command was specified.");
2027      return;
2028    }
2029
2030    if (num_args == 1) {
2031      // We're removing a root command, so we need to delete it from the
2032      // interpreter.
2033      const char *cmd_name = command.GetArgumentAtIndex(0);
2034      // Let's do a little more work here so we can do better error reporting.
2035      CommandInterpreter &interp = GetCommandInterpreter();
2036      CommandObjectSP cmd_sp = interp.GetCommandSPExact(cmd_name);
2037      if (!cmd_sp) {
2038        result.AppendErrorWithFormat("container command %s doesn't exist.",
2039                                     cmd_name);
2040        return;
2041      }
2042      if (!cmd_sp->IsUserCommand()) {
2043        result.AppendErrorWithFormat(
2044            "container command %s is not a user command", cmd_name);
2045        return;
2046      }
2047      if (!cmd_sp->GetAsMultiwordCommand()) {
2048        result.AppendErrorWithFormat("command %s is not a container command",
2049                                     cmd_name);
2050        return;
2051      }
2052
2053      bool did_remove = GetCommandInterpreter().RemoveUserMultiword(cmd_name);
2054      if (!did_remove) {
2055        result.AppendErrorWithFormat("error removing command %s.", cmd_name);
2056        return;
2057      }
2058
2059      result.SetStatus(eReturnStatusSuccessFinishNoResult);
2060      return;
2061    }
2062
2063    // We're removing a subcommand, first find the subcommand's owner:
2064    Status path_error;
2065    CommandObjectMultiword *container =
2066        GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
2067                                                           path_error);
2068
2069    if (!container) {
2070      result.AppendErrorWithFormat("error removing container command: %s",
2071                                   path_error.AsCString());
2072      return;
2073    }
2074    const char *leaf = command.GetArgumentAtIndex(num_args - 1);
2075    llvm::Error llvm_error =
2076        container->RemoveUserSubcommand(leaf, /* multiword okay */ true);
2077    if (llvm_error) {
2078      result.AppendErrorWithFormat("error removing container command: %s",
2079                                   llvm::toString(std::move(llvm_error)).c_str());
2080      return;
2081    }
2082    result.SetStatus(eReturnStatusSuccessFinishNoResult);
2083  }
2084};
2085
2086class CommandObjectCommandContainer : public CommandObjectMultiword {
2087public:
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, "
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
2110CommandObjectMultiwordCommands::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
2132CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
2133