xref: /llvm-project/lldb/source/Commands/CommandObjectCommands.cpp (revision 0642cd768b80665585c8500bed2933a3b99123dc)
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     AddSimpleArgumentList(eArgTypeFilename);
45   }
46 
47   ~CommandObjectCommandsSource() override = default;
48 
49   std::optional<std::string> GetRepeatCommand(Args &current_command_args,
50                                               uint32_t index) override {
51     return std::string("");
52   }
53 
54   Options *GetOptions() override { return &m_options; }
55 
56 protected:
57   class CommandOptions : public Options {
58   public:
59     CommandOptions()
60         : m_stop_on_error(true), m_silent_run(false), m_stop_on_continue(true),
61           m_cmd_relative_to_command_file(false) {}
62 
63     ~CommandOptions() override = default;
64 
65     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
66                           ExecutionContext *execution_context) override {
67       Status error;
68       const int short_option = m_getopt_table[option_idx].val;
69 
70       switch (short_option) {
71       case 'e':
72         error = m_stop_on_error.SetValueFromString(option_arg);
73         break;
74 
75       case 'c':
76         error = m_stop_on_continue.SetValueFromString(option_arg);
77         break;
78 
79       case 'C':
80         m_cmd_relative_to_command_file = true;
81         break;
82 
83       case 's':
84         error = m_silent_run.SetValueFromString(option_arg);
85         break;
86 
87       default:
88         llvm_unreachable("Unimplemented option");
89       }
90 
91       return error;
92     }
93 
94     void OptionParsingStarting(ExecutionContext *execution_context) override {
95       m_stop_on_error.Clear();
96       m_silent_run.Clear();
97       m_stop_on_continue.Clear();
98       m_cmd_relative_to_command_file.Clear();
99     }
100 
101     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
102       return llvm::ArrayRef(g_source_options);
103     }
104 
105     // Instance variables to hold the values for command options.
106 
107     OptionValueBoolean m_stop_on_error;
108     OptionValueBoolean m_silent_run;
109     OptionValueBoolean m_stop_on_continue;
110     OptionValueBoolean m_cmd_relative_to_command_file;
111   };
112 
113   void DoExecute(Args &command, CommandReturnObject &result) override {
114     if (command.GetArgumentCount() != 1) {
115       result.AppendErrorWithFormat(
116           "'%s' takes exactly one executable filename argument.\n",
117           GetCommandName().str().c_str());
118       return;
119     }
120 
121     FileSpec source_dir = {};
122     if (m_options.m_cmd_relative_to_command_file) {
123       source_dir = GetDebugger().GetCommandInterpreter().GetCurrentSourceDir();
124       if (!source_dir) {
125         result.AppendError("command source -C can only be specified "
126                            "from a command file");
127         result.SetStatus(eReturnStatusFailed);
128         return;
129       }
130     }
131 
132     FileSpec cmd_file(command[0].ref());
133     if (source_dir) {
134       // Prepend the source_dir to the cmd_file path:
135       if (!cmd_file.IsRelative()) {
136         result.AppendError("command source -C can only be used "
137                            "with a relative path.");
138         result.SetStatus(eReturnStatusFailed);
139         return;
140       }
141       cmd_file.MakeAbsolute(source_dir);
142     }
143 
144     FileSystem::Instance().Resolve(cmd_file);
145 
146     CommandInterpreterRunOptions options;
147     // If any options were set, then use them
148     if (m_options.m_stop_on_error.OptionWasSet() ||
149         m_options.m_silent_run.OptionWasSet() ||
150         m_options.m_stop_on_continue.OptionWasSet()) {
151       if (m_options.m_stop_on_continue.OptionWasSet())
152         options.SetStopOnContinue(
153             m_options.m_stop_on_continue.GetCurrentValue());
154 
155       if (m_options.m_stop_on_error.OptionWasSet())
156         options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue());
157 
158       // Individual silent setting is override for global command echo settings.
159       if (m_options.m_silent_run.GetCurrentValue()) {
160         options.SetSilent(true);
161       } else {
162         options.SetPrintResults(true);
163         options.SetPrintErrors(true);
164         options.SetEchoCommands(m_interpreter.GetEchoCommands());
165         options.SetEchoCommentCommands(m_interpreter.GetEchoCommentCommands());
166       }
167     }
168 
169     m_interpreter.HandleCommandsFromFile(cmd_file, options, result);
170   }
171 
172   CommandOptions m_options;
173 };
174 
175 #pragma mark CommandObjectCommandsAlias
176 // CommandObjectCommandsAlias
177 
178 #define LLDB_OPTIONS_alias
179 #include "CommandOptions.inc"
180 
181 static const char *g_python_command_instructions =
182     "Enter your Python command(s). Type 'DONE' to end.\n"
183     "You must define a Python function with this signature:\n"
184     "def my_command_impl(debugger, args, exe_ctx, result, internal_dict):\n";
185 
186 class CommandObjectCommandsAlias : public CommandObjectRaw {
187 protected:
188   class CommandOptions : public OptionGroup {
189   public:
190     CommandOptions() = default;
191 
192     ~CommandOptions() override = default;
193 
194     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
195       return llvm::ArrayRef(g_alias_options);
196     }
197 
198     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
199                           ExecutionContext *execution_context) override {
200       Status error;
201 
202       const int short_option = GetDefinitions()[option_idx].short_option;
203       std::string option_str(option_value);
204 
205       switch (short_option) {
206       case 'h':
207         m_help.SetCurrentValue(option_str);
208         m_help.SetOptionWasSet();
209         break;
210 
211       case 'H':
212         m_long_help.SetCurrentValue(option_str);
213         m_long_help.SetOptionWasSet();
214         break;
215 
216       default:
217         llvm_unreachable("Unimplemented option");
218       }
219 
220       return error;
221     }
222 
223     void OptionParsingStarting(ExecutionContext *execution_context) override {
224       m_help.Clear();
225       m_long_help.Clear();
226     }
227 
228     OptionValueString m_help;
229     OptionValueString m_long_help;
230   };
231 
232   OptionGroupOptions m_option_group;
233   CommandOptions m_command_options;
234 
235 public:
236   Options *GetOptions() override { return &m_option_group; }
237 
238   CommandObjectCommandsAlias(CommandInterpreter &interpreter)
239       : CommandObjectRaw(
240             interpreter, "command alias",
241             "Define a custom command in terms of an existing command.") {
242     m_option_group.Append(&m_command_options);
243     m_option_group.Finalize();
244 
245     SetHelpLong(
246         "'alias' allows the user to create a short-cut or abbreviation for long \
247 commands, multi-word commands, and commands that take particular options.  \
248 Below are some simple examples of how one might use the 'alias' command:"
249         R"(
250 
251 (lldb) command alias sc script
252 
253     Creates the abbreviation 'sc' for the 'script' command.
254 
255 (lldb) command alias bp breakpoint
256 
257 )"
258         "    Creates the abbreviation 'bp' for the 'breakpoint' command.  Since \
259 breakpoint commands are two-word commands, the user would still need to \
260 enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
261         R"(
262 
263 (lldb) command alias bpl breakpoint list
264 
265     Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
266 
267 )"
268         "An alias can include some options for the command, with the values either \
269 filled in at the time the alias is created, or specified as positional \
270 arguments, to be filled in when the alias is invoked.  The following example \
271 shows how to create aliases with options:"
272         R"(
273 
274 (lldb) command alias bfl breakpoint set -f %1 -l %2
275 
276 )"
277         "    Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
278 options already part of the alias.  So if the user wants to set a breakpoint \
279 by file and line without explicitly having to use the -f and -l options, the \
280 user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \
281 for the actual arguments that will be passed when the alias command is used.  \
282 The number in the placeholder refers to the position/order the actual value \
283 occupies when the alias is used.  All the occurrences of '%1' in the alias \
284 will be replaced with the first argument, all the occurrences of '%2' in the \
285 alias will be replaced with the second argument, and so on.  This also allows \
286 actual arguments to be used multiple times within an alias (see 'process \
287 launch' example below)."
288         R"(
289 
290 )"
291         "Note: the positional arguments must substitute as whole words in the resultant \
292 command, so you can't at present do something like this to append the file extension \
293 \".cpp\":"
294         R"(
295 
296 (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
297 
298 )"
299         "For more complex aliasing, use the \"command regex\" command instead.  In the \
300 'bfl' case above, the actual file value will be filled in with the first argument \
301 following 'bfl' and the actual line number value will be filled in with the second \
302 argument.  The user would use this alias as follows:"
303         R"(
304 
305 (lldb) command alias bfl breakpoint set -f %1 -l %2
306 (lldb) bfl my-file.c 137
307 
308 This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
309 
310 Another example:
311 
312 (lldb) command alias pltty process launch -s -o %1 -e %1
313 (lldb) pltty /dev/tty0
314 
315     Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
316 
317 )"
318         "If the user always wanted to pass the same value to a particular option, the \
319 alias could be defined with that value directly in the alias as a constant, \
320 rather than using a positional placeholder:"
321         R"(
322 
323 (lldb) command alias bl3 breakpoint set -f %1 -l 3
324 
325     Always sets a breakpoint on line 3 of whatever file is indicated.
326 
327 )"
328 
329         "If the alias abbreviation or the full alias command collides with another \
330 existing command, the command resolver will prefer to use the alias over any \
331 other command as far as there is only one alias command match.");
332 
333     CommandArgumentEntry arg1;
334     CommandArgumentEntry arg2;
335     CommandArgumentEntry arg3;
336     CommandArgumentData alias_arg;
337     CommandArgumentData cmd_arg;
338     CommandArgumentData options_arg;
339 
340     // Define the first (and only) variant of this arg.
341     alias_arg.arg_type = eArgTypeAliasName;
342     alias_arg.arg_repetition = eArgRepeatPlain;
343 
344     // There is only one variant this argument could be; put it into the
345     // argument entry.
346     arg1.push_back(alias_arg);
347 
348     // Define the first (and only) variant of this arg.
349     cmd_arg.arg_type = eArgTypeCommandName;
350     cmd_arg.arg_repetition = eArgRepeatPlain;
351 
352     // There is only one variant this argument could be; put it into the
353     // argument entry.
354     arg2.push_back(cmd_arg);
355 
356     // Define the first (and only) variant of this arg.
357     options_arg.arg_type = eArgTypeAliasOptions;
358     options_arg.arg_repetition = eArgRepeatOptional;
359 
360     // There is only one variant this argument could be; put it into the
361     // argument entry.
362     arg3.push_back(options_arg);
363 
364     // Push the data for the first argument into the m_arguments vector.
365     m_arguments.push_back(arg1);
366     m_arguments.push_back(arg2);
367     m_arguments.push_back(arg3);
368   }
369 
370   ~CommandObjectCommandsAlias() override = default;
371 
372 protected:
373   void DoExecute(llvm::StringRef raw_command_line,
374                  CommandReturnObject &result) override {
375     if (raw_command_line.empty()) {
376       result.AppendError("'command alias' requires at least two arguments");
377       return;
378     }
379 
380     ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
381     m_option_group.NotifyOptionParsingStarting(&exe_ctx);
382 
383     OptionsWithRaw args_with_suffix(raw_command_line);
384 
385     if (args_with_suffix.HasArgs())
386       if (!ParseOptionsAndNotify(args_with_suffix.GetArgs(), result,
387                                  m_option_group, exe_ctx))
388         return;
389 
390     llvm::StringRef raw_command_string = args_with_suffix.GetRawPart();
391     Args args(raw_command_string);
392 
393     if (args.GetArgumentCount() < 2) {
394       result.AppendError("'command alias' requires at least two arguments");
395       return;
396     }
397 
398     // Get the alias command.
399 
400     auto alias_command = args[0].ref();
401     if (alias_command.starts_with("-")) {
402       result.AppendError("aliases starting with a dash are not supported");
403       if (alias_command == "--help" || alias_command == "--long-help") {
404         result.AppendWarning("if trying to pass options to 'command alias' add "
405                              "a -- at the end of the options");
406       }
407       return;
408     }
409 
410     // Strip the new alias name off 'raw_command_string'  (leave it on args,
411     // which gets passed to 'Execute', which does the stripping itself.
412     size_t pos = raw_command_string.find(alias_command);
413     if (pos == 0) {
414       raw_command_string = raw_command_string.substr(alias_command.size());
415       pos = raw_command_string.find_first_not_of(' ');
416       if ((pos != std::string::npos) && (pos > 0))
417         raw_command_string = raw_command_string.substr(pos);
418     } else {
419       result.AppendError("Error parsing command string.  No alias created.");
420       return;
421     }
422 
423     // Verify that the command is alias-able.
424     if (m_interpreter.CommandExists(alias_command)) {
425       result.AppendErrorWithFormat(
426           "'%s' is a permanent debugger command and cannot be redefined.\n",
427           args[0].c_str());
428       return;
429     }
430 
431     if (m_interpreter.UserMultiwordCommandExists(alias_command)) {
432       result.AppendErrorWithFormat(
433           "'%s' is a user container command and cannot be overwritten.\n"
434           "Delete it first with 'command container delete'\n",
435           args[0].c_str());
436       return;
437     }
438 
439     // Get CommandObject that is being aliased. The command name is read from
440     // the front of raw_command_string. raw_command_string is returned with the
441     // name of the command object stripped off the front.
442     llvm::StringRef original_raw_command_string = raw_command_string;
443     CommandObject *cmd_obj =
444         m_interpreter.GetCommandObjectForCommand(raw_command_string);
445 
446     if (!cmd_obj) {
447       result.AppendErrorWithFormat("invalid command given to 'command alias'. "
448                                    "'%s' does not begin with a valid command."
449                                    "  No alias created.",
450                                    original_raw_command_string.str().c_str());
451     } else if (!cmd_obj->WantsRawCommandString()) {
452       // Note that args was initialized with the original command, and has not
453       // been updated to this point. Therefore can we pass it to the version of
454       // Execute that does not need/expect raw input in the alias.
455       HandleAliasingNormalCommand(args, result);
456     } else {
457       HandleAliasingRawCommand(alias_command, raw_command_string, *cmd_obj,
458                                result);
459     }
460   }
461 
462   bool HandleAliasingRawCommand(llvm::StringRef alias_command,
463                                 llvm::StringRef raw_command_string,
464                                 CommandObject &cmd_obj,
465                                 CommandReturnObject &result) {
466     // Verify & handle any options/arguments passed to the alias command
467 
468     OptionArgVectorSP option_arg_vector_sp =
469         OptionArgVectorSP(new OptionArgVector);
470 
471     const bool include_aliases = true;
472     // Look up the command using command's name first.  This is to resolve
473     // aliases when you are making nested aliases.  But if you don't find
474     // it that way, then it wasn't an alias and we can just use the object
475     // we were passed in.
476     CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact(
477             cmd_obj.GetCommandName(), include_aliases);
478     if (!cmd_obj_sp)
479       cmd_obj_sp = cmd_obj.shared_from_this();
480 
481     if (m_interpreter.AliasExists(alias_command) ||
482         m_interpreter.UserCommandExists(alias_command)) {
483       result.AppendWarningWithFormat(
484           "Overwriting existing definition for '%s'.\n",
485           alias_command.str().c_str());
486     }
487     if (CommandAlias *alias = m_interpreter.AddAlias(
488             alias_command, cmd_obj_sp, raw_command_string)) {
489       if (m_command_options.m_help.OptionWasSet())
490         alias->SetHelp(m_command_options.m_help.GetCurrentValue());
491       if (m_command_options.m_long_help.OptionWasSet())
492         alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
493       result.SetStatus(eReturnStatusSuccessFinishNoResult);
494     } else {
495       result.AppendError("Unable to create requested alias.\n");
496     }
497     return result.Succeeded();
498   }
499 
500   bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
501     size_t argc = args.GetArgumentCount();
502 
503     if (argc < 2) {
504       result.AppendError("'command alias' requires at least two arguments");
505       return false;
506     }
507 
508     // Save these in std::strings since we're going to shift them off.
509     const std::string alias_command(std::string(args[0].ref()));
510     const std::string actual_command(std::string(args[1].ref()));
511 
512     args.Shift(); // Shift the alias command word off the argument vector.
513     args.Shift(); // Shift the old command word off the argument vector.
514 
515     // Verify that the command is alias'able, and get the appropriate command
516     // object.
517 
518     if (m_interpreter.CommandExists(alias_command)) {
519       result.AppendErrorWithFormat(
520           "'%s' is a permanent debugger command and cannot be redefined.\n",
521           alias_command.c_str());
522       return false;
523     }
524 
525     if (m_interpreter.UserMultiwordCommandExists(alias_command)) {
526       result.AppendErrorWithFormat(
527           "'%s' is user container command and cannot be overwritten.\n"
528           "Delete it first with 'command container delete'",
529           alias_command.c_str());
530       return false;
531     }
532 
533     CommandObjectSP command_obj_sp(
534         m_interpreter.GetCommandSPExact(actual_command, true));
535     CommandObjectSP subcommand_obj_sp;
536     bool use_subcommand = false;
537     if (!command_obj_sp) {
538       result.AppendErrorWithFormat("'%s' is not an existing command.\n",
539                                    actual_command.c_str());
540       return false;
541     }
542     CommandObject *cmd_obj = command_obj_sp.get();
543     CommandObject *sub_cmd_obj = nullptr;
544     OptionArgVectorSP option_arg_vector_sp =
545         OptionArgVectorSP(new OptionArgVector);
546 
547     while (cmd_obj->IsMultiwordObject() && !args.empty()) {
548       auto sub_command = args[0].ref();
549       assert(!sub_command.empty());
550       subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command);
551       if (!subcommand_obj_sp) {
552         result.AppendErrorWithFormat(
553             "'%s' is not a valid sub-command of '%s'.  "
554             "Unable to create alias.\n",
555             args[0].c_str(), actual_command.c_str());
556         return false;
557       }
558 
559       sub_cmd_obj = subcommand_obj_sp.get();
560       use_subcommand = true;
561       args.Shift(); // Shift the sub_command word off the argument vector.
562       cmd_obj = sub_cmd_obj;
563     }
564 
565     // Verify & handle any options/arguments passed to the alias command
566 
567     std::string args_string;
568 
569     if (!args.empty()) {
570       CommandObjectSP tmp_sp =
571           m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName());
572       if (use_subcommand)
573         tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName());
574 
575       args.GetCommandString(args_string);
576     }
577 
578     if (m_interpreter.AliasExists(alias_command) ||
579         m_interpreter.UserCommandExists(alias_command)) {
580       result.AppendWarningWithFormat(
581           "Overwriting existing definition for '%s'.\n", alias_command.c_str());
582     }
583 
584     if (CommandAlias *alias = m_interpreter.AddAlias(
585             alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp,
586             args_string)) {
587       if (m_command_options.m_help.OptionWasSet())
588         alias->SetHelp(m_command_options.m_help.GetCurrentValue());
589       if (m_command_options.m_long_help.OptionWasSet())
590         alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
591       result.SetStatus(eReturnStatusSuccessFinishNoResult);
592     } else {
593       result.AppendError("Unable to create requested alias.\n");
594       return false;
595     }
596 
597     return result.Succeeded();
598   }
599 };
600 
601 #pragma mark CommandObjectCommandsUnalias
602 // CommandObjectCommandsUnalias
603 
604 class CommandObjectCommandsUnalias : public CommandObjectParsed {
605 public:
606   CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
607       : CommandObjectParsed(
608             interpreter, "command unalias",
609             "Delete one or more custom commands defined by 'command alias'.",
610             nullptr) {
611     AddSimpleArgumentList(eArgTypeAliasName);
612   }
613 
614   ~CommandObjectCommandsUnalias() override = default;
615 
616   void
617   HandleArgumentCompletion(CompletionRequest &request,
618                            OptionElementVector &opt_element_vector) override {
619     if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
620       return;
621 
622     for (const auto &ent : m_interpreter.GetAliases()) {
623       request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp());
624     }
625   }
626 
627 protected:
628   void DoExecute(Args &args, CommandReturnObject &result) override {
629     CommandObject::CommandMap::iterator pos;
630     CommandObject *cmd_obj;
631 
632     if (args.empty()) {
633       result.AppendError("must call 'unalias' with a valid alias");
634       return;
635     }
636 
637     auto command_name = args[0].ref();
638     cmd_obj = m_interpreter.GetCommandObject(command_name);
639     if (!cmd_obj) {
640       result.AppendErrorWithFormat(
641           "'%s' is not a known command.\nTry 'help' to see a "
642           "current list of commands.\n",
643           args[0].c_str());
644       return;
645     }
646 
647     if (m_interpreter.CommandExists(command_name)) {
648       if (cmd_obj->IsRemovable()) {
649         result.AppendErrorWithFormat(
650             "'%s' is not an alias, it is a debugger command which can be "
651             "removed using the 'command delete' command.\n",
652             args[0].c_str());
653       } else {
654         result.AppendErrorWithFormat(
655             "'%s' is a permanent debugger command and cannot be removed.\n",
656             args[0].c_str());
657       }
658       return;
659     }
660 
661     if (!m_interpreter.RemoveAlias(command_name)) {
662       if (m_interpreter.AliasExists(command_name))
663         result.AppendErrorWithFormat(
664             "Error occurred while attempting to unalias '%s'.\n",
665             args[0].c_str());
666       else
667         result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
668                                      args[0].c_str());
669       return;
670     }
671 
672     result.SetStatus(eReturnStatusSuccessFinishNoResult);
673   }
674 };
675 
676 #pragma mark CommandObjectCommandsDelete
677 // CommandObjectCommandsDelete
678 
679 class CommandObjectCommandsDelete : public CommandObjectParsed {
680 public:
681   CommandObjectCommandsDelete(CommandInterpreter &interpreter)
682       : CommandObjectParsed(
683             interpreter, "command delete",
684             "Delete one or more custom commands defined by 'command regex'.",
685             nullptr) {
686     AddSimpleArgumentList(eArgTypeCommandName);
687   }
688 
689   ~CommandObjectCommandsDelete() override = default;
690 
691   void
692   HandleArgumentCompletion(CompletionRequest &request,
693                            OptionElementVector &opt_element_vector) override {
694     if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
695       return;
696 
697     for (const auto &ent : m_interpreter.GetCommands()) {
698       if (ent.second->IsRemovable())
699         request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp());
700     }
701   }
702 
703 protected:
704   void DoExecute(Args &args, CommandReturnObject &result) override {
705     CommandObject::CommandMap::iterator pos;
706 
707     if (args.empty()) {
708       result.AppendErrorWithFormat("must call '%s' with one or more valid user "
709                                    "defined regular expression command names",
710                                    GetCommandName().str().c_str());
711       return;
712     }
713 
714     auto command_name = args[0].ref();
715     if (!m_interpreter.CommandExists(command_name)) {
716       StreamString error_msg_stream;
717       const bool generate_upropos = true;
718       const bool generate_type_lookup = false;
719       CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
720           &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(),
721           generate_upropos, generate_type_lookup);
722       result.AppendError(error_msg_stream.GetString());
723       return;
724     }
725 
726     if (!m_interpreter.RemoveCommand(command_name)) {
727       result.AppendErrorWithFormat(
728           "'%s' is a permanent debugger command and cannot be removed.\n",
729           args[0].c_str());
730       return;
731     }
732 
733     result.SetStatus(eReturnStatusSuccessFinishNoResult);
734   }
735 };
736 
737 // CommandObjectCommandsAddRegex
738 
739 #define LLDB_OPTIONS_regex
740 #include "CommandOptions.inc"
741 
742 #pragma mark CommandObjectCommandsAddRegex
743 
744 class CommandObjectCommandsAddRegex : public CommandObjectParsed,
745                                       public IOHandlerDelegateMultiline {
746 public:
747   CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
748       : CommandObjectParsed(
749             interpreter, "command regex",
750             "Define a custom command in terms of "
751             "existing commands by matching "
752             "regular expressions.",
753             "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
754         IOHandlerDelegateMultiline("",
755                                    IOHandlerDelegate::Completion::LLDBCommand) {
756     SetHelpLong(
757         R"(
758 )"
759         "This command allows the user to create powerful regular expression commands \
760 with substitutions. The regular expressions and substitutions are specified \
761 using the regular expression substitution format of:"
762         R"(
763 
764     s/<regex>/<subst>/
765 
766 )"
767         "<regex> is a regular expression that can use parenthesis to capture regular \
768 expression input and substitute the captured matches in the output using %1 \
769 for the first match, %2 for the second, and so on."
770         R"(
771 
772 )"
773         "The regular expressions can all be specified on the command line if more than \
774 one argument is provided. If just the command name is provided on the command \
775 line, then the regular expressions and substitutions can be entered on separate \
776 lines, followed by an empty line to terminate the command definition."
777         R"(
778 
779 EXAMPLES
780 
781 )"
782         "The following example will define a regular expression command named 'f' that \
783 will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
784 a number follows 'f':"
785         R"(
786 
787     (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
788     AddSimpleArgumentList(eArgTypeSEDStylePair, eArgRepeatOptional);
789   }
790 
791   ~CommandObjectCommandsAddRegex() override = default;
792 
793 protected:
794   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
795     StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
796     if (output_sp && interactive) {
797       output_sp->PutCString("Enter one or more sed substitution commands in "
798                             "the form: 's/<regex>/<subst>/'.\nTerminate the "
799                             "substitution list with an empty line.\n");
800       output_sp->Flush();
801     }
802   }
803 
804   void IOHandlerInputComplete(IOHandler &io_handler,
805                               std::string &data) override {
806     io_handler.SetIsDone(true);
807     if (m_regex_cmd_up) {
808       StringList lines;
809       if (lines.SplitIntoLines(data)) {
810         bool check_only = false;
811         for (const std::string &line : lines) {
812           Status error = AppendRegexSubstitution(line, check_only);
813           if (error.Fail()) {
814             if (!GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) {
815               StreamSP out_stream = GetDebugger().GetAsyncOutputStream();
816               out_stream->Printf("error: %s\n", error.AsCString());
817             }
818           }
819         }
820       }
821       if (m_regex_cmd_up->HasRegexEntries()) {
822         CommandObjectSP cmd_sp(m_regex_cmd_up.release());
823         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
824       }
825     }
826   }
827 
828   void DoExecute(Args &command, CommandReturnObject &result) override {
829     const size_t argc = command.GetArgumentCount();
830     if (argc == 0) {
831       result.AppendError("usage: 'command regex <command-name> "
832                          "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
833       return;
834     }
835 
836     Status error;
837     auto name = command[0].ref();
838     m_regex_cmd_up = std::make_unique<CommandObjectRegexCommand>(
839         m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 0,
840         true);
841 
842     if (argc == 1) {
843       Debugger &debugger = GetDebugger();
844       bool color_prompt = debugger.GetUseColor();
845       const bool multiple_lines = true; // Get multiple lines
846       IOHandlerSP io_handler_sp(new IOHandlerEditline(
847           debugger, IOHandler::Type::Other,
848           "lldb-regex",          // Name of input reader for history
849           llvm::StringRef("> "), // Prompt
850           llvm::StringRef(),     // Continuation prompt
851           multiple_lines, color_prompt,
852           0, // Don't show line numbers
853           *this));
854 
855       if (io_handler_sp) {
856         debugger.RunIOHandlerAsync(io_handler_sp);
857         result.SetStatus(eReturnStatusSuccessFinishNoResult);
858       }
859     } else {
860       for (auto &entry : command.entries().drop_front()) {
861         bool check_only = false;
862         error = AppendRegexSubstitution(entry.ref(), check_only);
863         if (error.Fail())
864           break;
865       }
866 
867       if (error.Success()) {
868         AddRegexCommandToInterpreter();
869       }
870     }
871     if (error.Fail()) {
872       result.AppendError(error.AsCString());
873     }
874   }
875 
876   Status AppendRegexSubstitution(const llvm::StringRef &regex_sed,
877                                  bool check_only) {
878     Status error;
879 
880     if (!m_regex_cmd_up) {
881       return Status::FromErrorStringWithFormat(
882           "invalid regular expression command object for: '%.*s'",
883           (int)regex_sed.size(), regex_sed.data());
884       return error;
885     }
886 
887     size_t regex_sed_size = regex_sed.size();
888 
889     if (regex_sed_size <= 1) {
890       return Status::FromErrorStringWithFormat(
891           "regular expression substitution string is too short: '%.*s'",
892           (int)regex_sed.size(), regex_sed.data());
893       return error;
894     }
895 
896     if (regex_sed[0] != 's') {
897       return Status::FromErrorStringWithFormat(
898           "regular expression substitution string "
899           "doesn't start with 's': '%.*s'",
900           (int)regex_sed.size(), regex_sed.data());
901       return error;
902     }
903     const size_t first_separator_char_pos = 1;
904     // use the char that follows 's' as the regex separator character so we can
905     // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
906     const char separator_char = regex_sed[first_separator_char_pos];
907     const size_t second_separator_char_pos =
908         regex_sed.find(separator_char, first_separator_char_pos + 1);
909 
910     if (second_separator_char_pos == std::string::npos) {
911       return Status::FromErrorStringWithFormat(
912           "missing second '%c' separator char after '%.*s' in '%.*s'",
913           separator_char,
914           (int)(regex_sed.size() - first_separator_char_pos - 1),
915           regex_sed.data() + (first_separator_char_pos + 1),
916           (int)regex_sed.size(), regex_sed.data());
917       return error;
918     }
919 
920     const size_t third_separator_char_pos =
921         regex_sed.find(separator_char, second_separator_char_pos + 1);
922 
923     if (third_separator_char_pos == std::string::npos) {
924       return Status::FromErrorStringWithFormat(
925           "missing third '%c' separator char after '%.*s' in '%.*s'",
926           separator_char,
927           (int)(regex_sed.size() - second_separator_char_pos - 1),
928           regex_sed.data() + (second_separator_char_pos + 1),
929           (int)regex_sed.size(), regex_sed.data());
930       return error;
931     }
932 
933     if (third_separator_char_pos != regex_sed_size - 1) {
934       // Make sure that everything that follows the last regex separator char
935       if (regex_sed.find_first_not_of("\t\n\v\f\r ",
936                                       third_separator_char_pos + 1) !=
937           std::string::npos) {
938         return Status::FromErrorStringWithFormat(
939             "extra data found after the '%.*s' regular expression substitution "
940             "string: '%.*s'",
941             (int)third_separator_char_pos + 1, regex_sed.data(),
942             (int)(regex_sed.size() - third_separator_char_pos - 1),
943             regex_sed.data() + (third_separator_char_pos + 1));
944         return error;
945       }
946     } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
947       return Status::FromErrorStringWithFormat(
948           "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
949           separator_char, separator_char, separator_char, (int)regex_sed.size(),
950           regex_sed.data());
951       return error;
952     } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
953       return Status::FromErrorStringWithFormat(
954           "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
955           separator_char, separator_char, separator_char, (int)regex_sed.size(),
956           regex_sed.data());
957       return error;
958     }
959 
960     if (!check_only) {
961       std::string regex(std::string(regex_sed.substr(
962           first_separator_char_pos + 1,
963           second_separator_char_pos - first_separator_char_pos - 1)));
964       std::string subst(std::string(regex_sed.substr(
965           second_separator_char_pos + 1,
966           third_separator_char_pos - second_separator_char_pos - 1)));
967       m_regex_cmd_up->AddRegexCommand(regex, subst);
968     }
969     return error;
970   }
971 
972   void AddRegexCommandToInterpreter() {
973     if (m_regex_cmd_up) {
974       if (m_regex_cmd_up->HasRegexEntries()) {
975         CommandObjectSP cmd_sp(m_regex_cmd_up.release());
976         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
977       }
978     }
979   }
980 
981 private:
982   std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_up;
983 
984   class CommandOptions : public Options {
985   public:
986     CommandOptions() = default;
987 
988     ~CommandOptions() override = default;
989 
990     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
991                           ExecutionContext *execution_context) override {
992       Status error;
993       const int short_option = m_getopt_table[option_idx].val;
994 
995       switch (short_option) {
996       case 'h':
997         m_help.assign(std::string(option_arg));
998         break;
999       case 's':
1000         m_syntax.assign(std::string(option_arg));
1001         break;
1002       default:
1003         llvm_unreachable("Unimplemented option");
1004       }
1005 
1006       return error;
1007     }
1008 
1009     void OptionParsingStarting(ExecutionContext *execution_context) override {
1010       m_help.clear();
1011       m_syntax.clear();
1012     }
1013 
1014     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1015       return llvm::ArrayRef(g_regex_options);
1016     }
1017 
1018     llvm::StringRef GetHelp() { return m_help; }
1019 
1020     llvm::StringRef GetSyntax() { return m_syntax; }
1021 
1022   protected:
1023     // Instance variables to hold the values for command options.
1024 
1025     std::string m_help;
1026     std::string m_syntax;
1027   };
1028 
1029   Options *GetOptions() override { return &m_options; }
1030 
1031   CommandOptions m_options;
1032 };
1033 
1034 class CommandObjectPythonFunction : public CommandObjectRaw {
1035 public:
1036   CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
1037                               std::string funct, std::string help,
1038                               ScriptedCommandSynchronicity synch,
1039                               CompletionType completion_type)
1040       : CommandObjectRaw(interpreter, name), m_function_name(funct),
1041         m_synchro(synch), m_completion_type(completion_type) {
1042     if (!help.empty())
1043       SetHelp(help);
1044     else {
1045       StreamString stream;
1046       stream.Printf("For more information run 'help %s'", name.c_str());
1047       SetHelp(stream.GetString());
1048     }
1049   }
1050 
1051   ~CommandObjectPythonFunction() override = default;
1052 
1053   bool IsRemovable() const override { return true; }
1054 
1055   const std::string &GetFunctionName() { return m_function_name; }
1056 
1057   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1058 
1059   llvm::StringRef GetHelpLong() override {
1060     if (m_fetched_help_long)
1061       return CommandObjectRaw::GetHelpLong();
1062 
1063     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1064     if (!scripter)
1065       return CommandObjectRaw::GetHelpLong();
1066 
1067     std::string docstring;
1068     m_fetched_help_long =
1069         scripter->GetDocumentationForItem(m_function_name.c_str(), docstring);
1070     if (!docstring.empty())
1071       SetHelpLong(docstring);
1072     return CommandObjectRaw::GetHelpLong();
1073   }
1074 
1075   void
1076   HandleArgumentCompletion(CompletionRequest &request,
1077                            OptionElementVector &opt_element_vector) override {
1078     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1079         GetCommandInterpreter(), m_completion_type, request, nullptr);
1080   }
1081 
1082   bool WantsCompletion() override { return true; }
1083 
1084 protected:
1085   void DoExecute(llvm::StringRef raw_command_line,
1086                  CommandReturnObject &result) override {
1087     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1088 
1089     m_interpreter.IncreaseCommandUsage(*this);
1090 
1091     Status error;
1092 
1093     result.SetStatus(eReturnStatusInvalid);
1094 
1095     if (!scripter || !scripter->RunScriptBasedCommand(
1096                          m_function_name.c_str(), raw_command_line, m_synchro,
1097                          result, error, m_exe_ctx)) {
1098       result.AppendError(error.AsCString());
1099     } else {
1100       // Don't change the status if the command already set it...
1101       if (result.GetStatus() == eReturnStatusInvalid) {
1102         if (result.GetOutputData().empty())
1103           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1104         else
1105           result.SetStatus(eReturnStatusSuccessFinishResult);
1106       }
1107     }
1108   }
1109 
1110 private:
1111   std::string m_function_name;
1112   ScriptedCommandSynchronicity m_synchro;
1113   bool m_fetched_help_long = false;
1114   CompletionType m_completion_type = eNoCompletion;
1115 };
1116 
1117 /// This class implements a "raw" scripted command.  lldb does no parsing of the
1118 /// command line, instead passing the line unaltered (except for backtick
1119 /// substitution).
1120 class CommandObjectScriptingObjectRaw : public CommandObjectRaw {
1121 public:
1122   CommandObjectScriptingObjectRaw(CommandInterpreter &interpreter,
1123                                   std::string name,
1124                                   StructuredData::GenericSP cmd_obj_sp,
1125                                   ScriptedCommandSynchronicity synch,
1126                                   CompletionType completion_type)
1127       : CommandObjectRaw(interpreter, name), m_cmd_obj_sp(cmd_obj_sp),
1128         m_synchro(synch), m_fetched_help_short(false),
1129         m_fetched_help_long(false), m_completion_type(completion_type) {
1130     StreamString stream;
1131     stream.Printf("For more information run 'help %s'", name.c_str());
1132     SetHelp(stream.GetString());
1133     if (ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter())
1134       GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
1135   }
1136 
1137   ~CommandObjectScriptingObjectRaw() override = default;
1138 
1139   void
1140   HandleArgumentCompletion(CompletionRequest &request,
1141                            OptionElementVector &opt_element_vector) override {
1142     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1143         GetCommandInterpreter(), m_completion_type, request, nullptr);
1144   }
1145 
1146   bool WantsCompletion() override { return true; }
1147 
1148   bool IsRemovable() const override { return true; }
1149 
1150   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1151 
1152   std::optional<std::string> GetRepeatCommand(Args &args,
1153                                               uint32_t index) override {
1154     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1155     if (!scripter)
1156       return std::nullopt;
1157 
1158     return scripter->GetRepeatCommandForScriptedCommand(m_cmd_obj_sp, args);
1159   }
1160 
1161   llvm::StringRef GetHelp() override {
1162     if (m_fetched_help_short)
1163       return CommandObjectRaw::GetHelp();
1164     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1165     if (!scripter)
1166       return CommandObjectRaw::GetHelp();
1167     std::string docstring;
1168     m_fetched_help_short =
1169         scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
1170     if (!docstring.empty())
1171       SetHelp(docstring);
1172 
1173     return CommandObjectRaw::GetHelp();
1174   }
1175 
1176   llvm::StringRef GetHelpLong() override {
1177     if (m_fetched_help_long)
1178       return CommandObjectRaw::GetHelpLong();
1179 
1180     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1181     if (!scripter)
1182       return CommandObjectRaw::GetHelpLong();
1183 
1184     std::string docstring;
1185     m_fetched_help_long =
1186         scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
1187     if (!docstring.empty())
1188       SetHelpLong(docstring);
1189     return CommandObjectRaw::GetHelpLong();
1190   }
1191 
1192 protected:
1193   void DoExecute(llvm::StringRef raw_command_line,
1194                  CommandReturnObject &result) override {
1195     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1196 
1197     Status error;
1198 
1199     result.SetStatus(eReturnStatusInvalid);
1200 
1201     if (!scripter ||
1202         !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1203                                          m_synchro, result, error, m_exe_ctx)) {
1204       result.AppendError(error.AsCString());
1205     } else {
1206       // Don't change the status if the command already set it...
1207       if (result.GetStatus() == eReturnStatusInvalid) {
1208         if (result.GetOutputData().empty())
1209           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1210         else
1211           result.SetStatus(eReturnStatusSuccessFinishResult);
1212       }
1213     }
1214   }
1215 
1216 private:
1217   StructuredData::GenericSP m_cmd_obj_sp;
1218   ScriptedCommandSynchronicity m_synchro;
1219   bool m_fetched_help_short : 1;
1220   bool m_fetched_help_long : 1;
1221   CompletionType m_completion_type = eNoCompletion;
1222 };
1223 
1224 
1225 /// This command implements a lldb parsed scripted command.  The command
1226 /// provides a definition of the options and arguments, and a option value
1227 /// setting callback, and then the command's execution function gets passed
1228 /// just the parsed arguments.
1229 /// Note, implementing a command in Python using these base interfaces is a bit
1230 /// of a pain, but it is much easier to export this low level interface, and
1231 /// then make it nicer on the Python side, than to try to do that in a
1232 /// script language neutral way.
1233 /// So I've also added a base class in Python that provides a table-driven
1234 /// way of defining the options and arguments, which automatically fills the
1235 /// option values, making them available as properties in Python.
1236 ///
1237 class CommandObjectScriptingObjectParsed : public CommandObjectParsed {
1238 private:
1239   class CommandOptions : public Options {
1240   public:
1241     CommandOptions(CommandInterpreter &interpreter,
1242         StructuredData::GenericSP cmd_obj_sp) : m_interpreter(interpreter),
1243             m_cmd_obj_sp(cmd_obj_sp) {}
1244 
1245     ~CommandOptions() override = default;
1246 
1247     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1248                           ExecutionContext *execution_context) override {
1249       Status error;
1250       ScriptInterpreter *scripter =
1251         m_interpreter.GetDebugger().GetScriptInterpreter();
1252       if (!scripter) {
1253         return Status::FromErrorString(
1254             "No script interpreter for SetOptionValue.");
1255         return error;
1256       }
1257       if (!m_cmd_obj_sp) {
1258         return Status::FromErrorString(
1259             "SetOptionValue called with empty cmd_obj.");
1260         return error;
1261       }
1262       if (!m_options_definition_up) {
1263         return Status::FromErrorString(
1264             "SetOptionValue called before options definitions "
1265             "were created.");
1266         return error;
1267       }
1268       // Pass the long option, since you aren't actually required to have a
1269       // short_option, and for those options the index or short option character
1270       // aren't meaningful on the python side.
1271       const char * long_option =
1272         m_options_definition_up.get()[option_idx].long_option;
1273       bool success = scripter->SetOptionValueForCommandObject(m_cmd_obj_sp,
1274         execution_context, long_option, option_arg);
1275       if (!success)
1276         return Status::FromErrorStringWithFormatv(
1277             "Error setting option: {0} to {1}", long_option, option_arg);
1278       return error;
1279     }
1280 
1281     void OptionParsingStarting(ExecutionContext *execution_context) override {
1282       ScriptInterpreter *scripter =
1283         m_interpreter.GetDebugger().GetScriptInterpreter();
1284       if (!scripter || !m_cmd_obj_sp)
1285         return;
1286 
1287       scripter->OptionParsingStartedForCommandObject(m_cmd_obj_sp);
1288     }
1289 
1290     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1291       if (!m_options_definition_up)
1292         return {};
1293       return llvm::ArrayRef(m_options_definition_up.get(), m_num_options);
1294     }
1295 
1296     static Status ParseUsageMaskFromArray(StructuredData::ObjectSP obj_sp,
1297         size_t counter, uint32_t &usage_mask) {
1298       // If the usage entry is not provided, we use LLDB_OPT_SET_ALL.
1299       // If the usage mask is a UINT, the option belongs to that group.
1300       // If the usage mask is a vector of UINT's, the option belongs to all the
1301       // groups listed.
1302       // If a subelement of the vector is a vector of two ints, then the option
1303       // belongs to the inclusive range from the first to the second element.
1304       Status error;
1305       if (!obj_sp) {
1306         usage_mask = LLDB_OPT_SET_ALL;
1307         return error;
1308       }
1309 
1310       usage_mask = 0;
1311 
1312       StructuredData::UnsignedInteger *uint_val =
1313           obj_sp->GetAsUnsignedInteger();
1314       if (uint_val) {
1315         // If this is an integer, then this specifies a single group:
1316         uint32_t value = uint_val->GetValue();
1317         if (value == 0) {
1318           return Status::FromErrorStringWithFormatv(
1319               "0 is not a valid group for option {0}", counter);
1320         }
1321         usage_mask = (1 << (value - 1));
1322         return error;
1323       }
1324       // Otherwise it has to be an array:
1325       StructuredData::Array *array_val = obj_sp->GetAsArray();
1326       if (!array_val) {
1327         return Status::FromErrorStringWithFormatv(
1328             "required field is not a array for option {0}", counter);
1329       }
1330       // This is the array ForEach for accumulating a group usage mask from
1331       // an array of string descriptions of groups.
1332       auto groups_accumulator
1333           = [counter, &usage_mask, &error]
1334             (StructuredData::Object *obj) -> bool {
1335         StructuredData::UnsignedInteger *int_val = obj->GetAsUnsignedInteger();
1336         if (int_val) {
1337           uint32_t value = int_val->GetValue();
1338           if (value == 0) {
1339             error = Status::FromErrorStringWithFormatv(
1340                 "0 is not a valid group for element {0}", counter);
1341             return false;
1342           }
1343           usage_mask |= (1 << (value - 1));
1344           return true;
1345         }
1346         StructuredData::Array *arr_val = obj->GetAsArray();
1347         if (!arr_val) {
1348           error = Status::FromErrorStringWithFormatv(
1349               "Group element not an int or array of integers for element {0}",
1350               counter);
1351           return false;
1352         }
1353         size_t num_range_elem = arr_val->GetSize();
1354         if (num_range_elem != 2) {
1355           error = Status::FromErrorStringWithFormatv(
1356               "Subranges of a group not a start and a stop for element {0}",
1357               counter);
1358           return false;
1359         }
1360         int_val = arr_val->GetItemAtIndex(0)->GetAsUnsignedInteger();
1361         if (!int_val) {
1362           error = Status::FromErrorStringWithFormatv(
1363               "Start element of a subrange of a "
1364               "group not unsigned int for element {0}",
1365               counter);
1366           return false;
1367         }
1368         uint32_t start = int_val->GetValue();
1369         int_val = arr_val->GetItemAtIndex(1)->GetAsUnsignedInteger();
1370         if (!int_val) {
1371           error = Status::FromErrorStringWithFormatv(
1372               "End element of a subrange of a group"
1373               " not unsigned int for element {0}",
1374               counter);
1375           return false;
1376         }
1377         uint32_t end = int_val->GetValue();
1378         if (start == 0 || end == 0 || start > end) {
1379           error = Status::FromErrorStringWithFormatv(
1380               "Invalid subrange of a group: {0} - "
1381               "{1} for element {2}",
1382               start, end, counter);
1383           return false;
1384         }
1385         for (uint32_t i = start; i <= end; i++) {
1386           usage_mask |= (1 << (i - 1));
1387         }
1388         return true;
1389       };
1390       array_val->ForEach(groups_accumulator);
1391       return error;
1392     }
1393 
1394 
1395     Status SetOptionsFromArray(StructuredData::Dictionary &options) {
1396       Status error;
1397       m_num_options = options.GetSize();
1398       m_options_definition_up.reset(new OptionDefinition[m_num_options]);
1399       // We need to hand out pointers to contents of these vectors; we reserve
1400       // as much as we'll need up front so they don't get freed on resize...
1401       m_usage_container.resize(m_num_options);
1402       m_enum_storage.resize(m_num_options);
1403       m_enum_vector.resize(m_num_options);
1404 
1405       size_t counter = 0;
1406       size_t short_opt_counter = 0;
1407       // This is the Array::ForEach function for adding option elements:
1408       auto add_element = [this, &error, &counter, &short_opt_counter]
1409           (llvm::StringRef long_option, StructuredData::Object *object) -> bool {
1410         StructuredData::Dictionary *opt_dict = object->GetAsDictionary();
1411         if (!opt_dict) {
1412           error = Status::FromErrorString(
1413               "Value in options dictionary is not a dictionary");
1414           return false;
1415         }
1416         OptionDefinition &option_def = m_options_definition_up.get()[counter];
1417 
1418         // We aren't exposing the validator yet, set it to null
1419         option_def.validator = nullptr;
1420         // We don't require usage masks, so set it to one group by default:
1421         option_def.usage_mask = 1;
1422 
1423         // Now set the fields of the OptionDefinition Array from the dictionary:
1424         //
1425         // Note that I don't check for unknown fields in the option dictionaries
1426         // so a scriptor can add extra elements that are helpful when they go to
1427         // do "set_option_value"
1428 
1429         // Usage Mask:
1430         StructuredData::ObjectSP obj_sp = opt_dict->GetValueForKey("groups");
1431         if (obj_sp) {
1432           error = ParseUsageMaskFromArray(obj_sp, counter,
1433                                           option_def.usage_mask);
1434           if (error.Fail())
1435             return false;
1436         }
1437 
1438         // Required:
1439         option_def.required = false;
1440         obj_sp = opt_dict->GetValueForKey("required");
1441         if (obj_sp) {
1442           StructuredData::Boolean *boolean_val = obj_sp->GetAsBoolean();
1443           if (!boolean_val) {
1444             error = Status::FromErrorStringWithFormatv(
1445                 "'required' field is not a boolean "
1446                 "for option {0}",
1447                 counter);
1448             return false;
1449           }
1450           option_def.required = boolean_val->GetValue();
1451         }
1452 
1453         // Short Option:
1454         int short_option;
1455         obj_sp = opt_dict->GetValueForKey("short_option");
1456         if (obj_sp) {
1457           // The value is a string, so pull the
1458           llvm::StringRef short_str = obj_sp->GetStringValue();
1459           if (short_str.empty()) {
1460             error = Status::FromErrorStringWithFormatv(
1461                 "short_option field empty for "
1462                 "option {0}",
1463                 counter);
1464             return false;
1465           } else if (short_str.size() != 1) {
1466             error = Status::FromErrorStringWithFormatv(
1467                 "short_option field has extra "
1468                 "characters for option {0}",
1469                 counter);
1470             return false;
1471           }
1472           short_option = (int) short_str[0];
1473         } else {
1474           // If the short option is not provided, then we need a unique value
1475           // less than the lowest printable ASCII character.
1476           short_option = short_opt_counter++;
1477         }
1478         option_def.short_option = short_option;
1479 
1480         // Long Option is the key from the outer dict:
1481         if (long_option.empty()) {
1482           error = Status::FromErrorStringWithFormatv(
1483               "empty long_option for option {0}", counter);
1484           return false;
1485         }
1486         auto inserted = g_string_storer.insert(long_option.str());
1487         option_def.long_option = ((*(inserted.first)).data());
1488 
1489         // Value Type:
1490         obj_sp = opt_dict->GetValueForKey("value_type");
1491         if (obj_sp) {
1492           StructuredData::UnsignedInteger *uint_val
1493               = obj_sp->GetAsUnsignedInteger();
1494           if (!uint_val) {
1495             error = Status::FromErrorStringWithFormatv(
1496                 "Value type must be an unsigned "
1497                 "integer");
1498             return false;
1499           }
1500           uint64_t val_type = uint_val->GetValue();
1501           if (val_type >= eArgTypeLastArg) {
1502             error =
1503                 Status::FromErrorStringWithFormatv("Value type {0} beyond the "
1504                                                    "CommandArgumentType bounds",
1505                                                    val_type);
1506             return false;
1507           }
1508           option_def.argument_type = (CommandArgumentType) val_type;
1509           option_def.option_has_arg = true;
1510         } else {
1511           option_def.argument_type = eArgTypeNone;
1512           option_def.option_has_arg = false;
1513         }
1514 
1515         // Completion Type:
1516         obj_sp = opt_dict->GetValueForKey("completion_type");
1517         if (obj_sp) {
1518           StructuredData::UnsignedInteger *uint_val = obj_sp->GetAsUnsignedInteger();
1519           if (!uint_val) {
1520             error = Status::FromErrorStringWithFormatv(
1521                 "Completion type must be an "
1522                 "unsigned integer for option {0}",
1523                 counter);
1524             return false;
1525           }
1526           uint64_t completion_type = uint_val->GetValue();
1527           if (completion_type > eCustomCompletion) {
1528             error = Status::FromErrorStringWithFormatv(
1529                 "Completion type for option {0} "
1530                 "beyond the CompletionType bounds",
1531                 completion_type);
1532             return false;
1533           }
1534           option_def.completion_type = (CommandArgumentType) completion_type;
1535         } else
1536           option_def.completion_type = eNoCompletion;
1537 
1538         // Usage Text:
1539         std::string usage_text;
1540         obj_sp = opt_dict->GetValueForKey("help");
1541         if (!obj_sp) {
1542           error = Status::FromErrorStringWithFormatv(
1543               "required usage missing from option "
1544               "{0}",
1545               counter);
1546           return false;
1547         }
1548         llvm::StringRef usage_stref;
1549         usage_stref = obj_sp->GetStringValue();
1550         if (usage_stref.empty()) {
1551           error = Status::FromErrorStringWithFormatv(
1552               "empty usage text for option {0}", counter);
1553           return false;
1554         }
1555         m_usage_container[counter] = usage_stref.str().c_str();
1556         option_def.usage_text = m_usage_container[counter].data();
1557 
1558         // Enum Values:
1559 
1560         obj_sp = opt_dict->GetValueForKey("enum_values");
1561         if (obj_sp) {
1562           StructuredData::Array *array = obj_sp->GetAsArray();
1563           if (!array) {
1564             error = Status::FromErrorStringWithFormatv(
1565                 "enum values must be an array for "
1566                 "option {0}",
1567                 counter);
1568             return false;
1569           }
1570           size_t num_elem = array->GetSize();
1571           size_t enum_ctr = 0;
1572           m_enum_storage[counter] = std::vector<EnumValueStorage>(num_elem);
1573           std::vector<EnumValueStorage> &curr_elem = m_enum_storage[counter];
1574 
1575           // This is the Array::ForEach function for adding enum elements:
1576           // Since there are only two fields to specify the enum, use a simple
1577           // two element array with value first, usage second.
1578           // counter is only used for reporting so I pass it by value here.
1579           auto add_enum = [&enum_ctr, &curr_elem, counter, &error]
1580               (StructuredData::Object *object) -> bool {
1581             StructuredData::Array *enum_arr = object->GetAsArray();
1582             if (!enum_arr) {
1583               error = Status::FromErrorStringWithFormatv(
1584                   "Enum values for option {0} not "
1585                   "an array",
1586                   counter);
1587               return false;
1588             }
1589             size_t num_enum_elements = enum_arr->GetSize();
1590             if (num_enum_elements != 2) {
1591               error = Status::FromErrorStringWithFormatv(
1592                   "Wrong number of elements: {0} "
1593                   "for enum {1} in option {2}",
1594                   num_enum_elements, enum_ctr, counter);
1595               return false;
1596             }
1597             // Enum Value:
1598             StructuredData::ObjectSP obj_sp = enum_arr->GetItemAtIndex(0);
1599             llvm::StringRef val_stref = obj_sp->GetStringValue();
1600             std::string value_cstr_str = val_stref.str().c_str();
1601 
1602             // Enum Usage:
1603             obj_sp = enum_arr->GetItemAtIndex(1);
1604             if (!obj_sp) {
1605               error = Status::FromErrorStringWithFormatv(
1606                   "No usage for enum {0} in option "
1607                   "{1}",
1608                   enum_ctr, counter);
1609               return false;
1610             }
1611             llvm::StringRef usage_stref = obj_sp->GetStringValue();
1612             std::string usage_cstr_str = usage_stref.str().c_str();
1613             curr_elem[enum_ctr] = EnumValueStorage(value_cstr_str,
1614                 usage_cstr_str, enum_ctr);
1615 
1616             enum_ctr++;
1617             return true;
1618           }; // end of add_enum
1619 
1620           array->ForEach(add_enum);
1621           if (!error.Success())
1622             return false;
1623           // We have to have a vector of elements to set in the options, make
1624           // that here:
1625           for (auto &elem : curr_elem)
1626             m_enum_vector[counter].emplace_back(elem.element);
1627 
1628           option_def.enum_values = llvm::ArrayRef(m_enum_vector[counter]);
1629         }
1630         counter++;
1631         return true;
1632       }; // end of add_element
1633 
1634       options.ForEach(add_element);
1635       return error;
1636     }
1637 
1638     size_t GetNumOptions() { return m_num_options; }
1639 
1640   private:
1641     struct EnumValueStorage {
1642       EnumValueStorage() {
1643         element.string_value = "value not set";
1644         element.usage = "usage not set";
1645         element.value = 0;
1646       }
1647 
1648       EnumValueStorage(std::string in_str_val, std::string in_usage,
1649           size_t in_value) : value(std::move(in_str_val)), usage(std::move(in_usage)) {
1650         SetElement(in_value);
1651       }
1652 
1653       EnumValueStorage(const EnumValueStorage &in) : value(in.value),
1654           usage(in.usage) {
1655         SetElement(in.element.value);
1656       }
1657 
1658       EnumValueStorage &operator=(const EnumValueStorage &in) {
1659         value = in.value;
1660         usage = in.usage;
1661         SetElement(in.element.value);
1662         return *this;
1663       }
1664 
1665       void SetElement(size_t in_value) {
1666         element.value = in_value;
1667         element.string_value = value.data();
1668         element.usage = usage.data();
1669       }
1670 
1671       std::string value;
1672       std::string usage;
1673       OptionEnumValueElement element;
1674     };
1675     // We have to provide char * values for the long option, usage and enum
1676     // values, that's what the option definitions hold.
1677     // The long option strings are quite likely to be reused in other added
1678     // commands, so those are stored in a global set: g_string_storer.
1679     // But the usages are much less likely to be reused, so those are stored in
1680     // a vector in the command instance.  It gets resized to the correct size
1681     // and then filled with null-terminated strings in the std::string, so the
1682     // are valid C-strings that won't move around.
1683     // The enum values and descriptions are treated similarly - these aren't
1684     // all that common so it's not worth the effort to dedup them.
1685     size_t m_num_options = 0;
1686     std::unique_ptr<OptionDefinition> m_options_definition_up;
1687     std::vector<std::vector<EnumValueStorage>> m_enum_storage;
1688     std::vector<std::vector<OptionEnumValueElement>> m_enum_vector;
1689     std::vector<std::string> m_usage_container;
1690     CommandInterpreter &m_interpreter;
1691     StructuredData::GenericSP m_cmd_obj_sp;
1692     static std::unordered_set<std::string> g_string_storer;
1693   };
1694 
1695 public:
1696   static CommandObjectSP Create(CommandInterpreter &interpreter,
1697                 std::string name,
1698                 StructuredData::GenericSP cmd_obj_sp,
1699                 ScriptedCommandSynchronicity synch,
1700                 CommandReturnObject &result) {
1701     CommandObjectSP new_cmd_sp(new CommandObjectScriptingObjectParsed(
1702         interpreter, name, cmd_obj_sp, synch));
1703 
1704     CommandObjectScriptingObjectParsed *parsed_cmd
1705         = static_cast<CommandObjectScriptingObjectParsed *>(new_cmd_sp.get());
1706     // Now check all the failure modes, and report if found.
1707     Status opt_error = parsed_cmd->GetOptionsError();
1708     Status arg_error = parsed_cmd->GetArgsError();
1709 
1710     if (opt_error.Fail())
1711       result.AppendErrorWithFormat("failed to parse option definitions: %s",
1712                                    opt_error.AsCString());
1713     if (arg_error.Fail())
1714       result.AppendErrorWithFormat("%sfailed to parse argument definitions: %s",
1715                                    opt_error.Fail() ? ", also " : "",
1716                                    arg_error.AsCString());
1717 
1718     if (!result.Succeeded())
1719       return {};
1720 
1721     return new_cmd_sp;
1722   }
1723 
1724   CommandObjectScriptingObjectParsed(CommandInterpreter &interpreter,
1725                                std::string name,
1726                                StructuredData::GenericSP cmd_obj_sp,
1727                                ScriptedCommandSynchronicity synch)
1728       : CommandObjectParsed(interpreter, name.c_str()),
1729         m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch),
1730         m_options(interpreter, cmd_obj_sp), m_fetched_help_short(false),
1731         m_fetched_help_long(false) {
1732     StreamString stream;
1733     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1734     if (!scripter) {
1735       m_options_error = Status::FromErrorString("No script interpreter");
1736       return;
1737     }
1738 
1739     // Set the flags:
1740     GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
1741 
1742     // Now set up the options definitions from the options:
1743     StructuredData::ObjectSP options_object_sp
1744         = scripter->GetOptionsForCommandObject(cmd_obj_sp);
1745     // It's okay not to have an options dict.
1746     if (options_object_sp) {
1747       // The options come as a dictionary of dictionaries.  The key of the
1748       // outer dict is the long option name (since that's required).  The
1749       // value holds all the other option specification bits.
1750       StructuredData::Dictionary *options_dict
1751           = options_object_sp->GetAsDictionary();
1752       // but if it exists, it has to be an array.
1753       if (options_dict) {
1754         m_options_error = m_options.SetOptionsFromArray(*(options_dict));
1755         // If we got an error don't bother with the arguments...
1756         if (m_options_error.Fail())
1757           return;
1758       } else {
1759         m_options_error = Status::FromErrorString("Options array not an array");
1760         return;
1761       }
1762     }
1763     // Then fetch the args.  Since the arguments can have usage masks you need
1764     // an array of arrays.
1765     StructuredData::ObjectSP args_object_sp
1766       = scripter->GetArgumentsForCommandObject(cmd_obj_sp);
1767     if (args_object_sp) {
1768       StructuredData::Array *args_array = args_object_sp->GetAsArray();
1769       if (!args_array) {
1770         m_args_error =
1771             Status::FromErrorString("Argument specification is not an array");
1772         return;
1773       }
1774       size_t counter = 0;
1775 
1776       // This is the Array::ForEach function that handles the
1777       // CommandArgumentEntry arrays one by one:
1778       auto arg_array_adder = [this, &counter] (StructuredData::Object *object)
1779           -> bool {
1780         // This is the Array::ForEach function to add argument entries:
1781         CommandArgumentEntry this_entry;
1782         size_t elem_counter = 0;
1783         auto args_adder = [this, counter, &elem_counter, &this_entry]
1784             (StructuredData::Object *object) -> bool {
1785           // The arguments definition has three fields, the argument type, the
1786           // repeat and the usage mask.
1787           CommandArgumentType arg_type = eArgTypeNone;
1788           ArgumentRepetitionType arg_repetition = eArgRepeatOptional;
1789           uint32_t arg_opt_set_association;
1790 
1791           auto report_error = [this, elem_counter,
1792                                counter](const char *err_txt) -> bool {
1793             m_args_error = Status::FromErrorStringWithFormatv(
1794                 "Element {0} of arguments "
1795                 "list element {1}: %s.",
1796                 elem_counter, counter, err_txt);
1797             return false;
1798           };
1799 
1800           StructuredData::Dictionary *arg_dict = object->GetAsDictionary();
1801           if (!arg_dict) {
1802             report_error("is not a dictionary.");
1803             return false;
1804           }
1805           // Argument Type:
1806           StructuredData::ObjectSP obj_sp
1807               = arg_dict->GetValueForKey("arg_type");
1808           if (obj_sp) {
1809             StructuredData::UnsignedInteger *uint_val
1810                 = obj_sp->GetAsUnsignedInteger();
1811             if (!uint_val) {
1812               report_error("value type must be an unsigned integer");
1813               return false;
1814             }
1815             uint64_t arg_type_int = uint_val->GetValue();
1816             if (arg_type_int >= eArgTypeLastArg) {
1817               report_error("value type beyond ArgumentRepetitionType bounds");
1818               return false;
1819             }
1820             arg_type = (CommandArgumentType) arg_type_int;
1821           }
1822           // Repeat Value:
1823           obj_sp = arg_dict->GetValueForKey("repeat");
1824           std::optional<ArgumentRepetitionType> repeat;
1825           if (obj_sp) {
1826             llvm::StringRef repeat_str = obj_sp->GetStringValue();
1827             if (repeat_str.empty()) {
1828               report_error("repeat value is empty");
1829               return false;
1830             }
1831             repeat = ArgRepetitionFromString(repeat_str);
1832             if (!repeat) {
1833               report_error("invalid repeat value");
1834               return false;
1835             }
1836             arg_repetition = *repeat;
1837           }
1838 
1839           // Usage Mask:
1840           obj_sp = arg_dict->GetValueForKey("groups");
1841           m_args_error = CommandOptions::ParseUsageMaskFromArray(obj_sp,
1842               counter, arg_opt_set_association);
1843           this_entry.emplace_back(arg_type, arg_repetition,
1844               arg_opt_set_association);
1845           elem_counter++;
1846           return true;
1847         };
1848         StructuredData::Array *args_array = object->GetAsArray();
1849         if (!args_array) {
1850           m_args_error =
1851               Status::FromErrorStringWithFormatv("Argument definition element "
1852                                                  "{0} is not an array",
1853                                                  counter);
1854         }
1855 
1856         args_array->ForEach(args_adder);
1857         if (m_args_error.Fail())
1858           return false;
1859         if (this_entry.empty()) {
1860           m_args_error =
1861               Status::FromErrorStringWithFormatv("Argument definition element "
1862                                                  "{0} is empty",
1863                                                  counter);
1864           return false;
1865         }
1866         m_arguments.push_back(this_entry);
1867         counter++;
1868         return true;
1869       }; // end of arg_array_adder
1870       // Here we actually parse the args definition:
1871       args_array->ForEach(arg_array_adder);
1872     }
1873   }
1874 
1875   ~CommandObjectScriptingObjectParsed() override = default;
1876 
1877   Status GetOptionsError() { return m_options_error; }
1878   Status GetArgsError() { return m_args_error; }
1879   bool WantsCompletion() override { return true; }
1880 
1881   bool IsRemovable() const override { return true; }
1882 
1883   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1884 
1885   std::optional<std::string> GetRepeatCommand(Args &args,
1886                                               uint32_t index) override {
1887     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1888     if (!scripter)
1889       return std::nullopt;
1890 
1891     return scripter->GetRepeatCommandForScriptedCommand(m_cmd_obj_sp, args);
1892   }
1893 
1894   llvm::StringRef GetHelp() override {
1895     if (m_fetched_help_short)
1896       return CommandObjectParsed::GetHelp();
1897     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1898     if (!scripter)
1899       return CommandObjectParsed::GetHelp();
1900     std::string docstring;
1901     m_fetched_help_short =
1902         scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
1903     if (!docstring.empty())
1904       SetHelp(docstring);
1905 
1906     return CommandObjectParsed::GetHelp();
1907   }
1908 
1909   llvm::StringRef GetHelpLong() override {
1910     if (m_fetched_help_long)
1911       return CommandObjectParsed::GetHelpLong();
1912 
1913     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1914     if (!scripter)
1915       return CommandObjectParsed::GetHelpLong();
1916 
1917     std::string docstring;
1918     m_fetched_help_long =
1919         scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
1920     if (!docstring.empty())
1921       SetHelpLong(docstring);
1922     return CommandObjectParsed::GetHelpLong();
1923   }
1924 
1925   Options *GetOptions() override {
1926     // CommandObjectParsed requires that a command with no options return
1927     // nullptr.
1928     if (m_options.GetNumOptions() == 0)
1929       return nullptr;
1930     return &m_options;
1931   }
1932 
1933 protected:
1934   void DoExecute(Args &args,
1935                  CommandReturnObject &result) override {
1936     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1937 
1938     Status error;
1939 
1940     result.SetStatus(eReturnStatusInvalid);
1941 
1942     if (!scripter ||
1943         !scripter->RunScriptBasedParsedCommand(m_cmd_obj_sp, args,
1944                                          m_synchro, result, error, m_exe_ctx)) {
1945       result.AppendError(error.AsCString());
1946     } else {
1947       // Don't change the status if the command already set it...
1948       if (result.GetStatus() == eReturnStatusInvalid) {
1949         if (result.GetOutputData().empty())
1950           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1951         else
1952           result.SetStatus(eReturnStatusSuccessFinishResult);
1953       }
1954     }
1955   }
1956 
1957 private:
1958   StructuredData::GenericSP m_cmd_obj_sp;
1959   ScriptedCommandSynchronicity m_synchro;
1960   CommandOptions m_options;
1961   Status m_options_error;
1962   Status m_args_error;
1963   bool m_fetched_help_short : 1;
1964   bool m_fetched_help_long : 1;
1965 };
1966 
1967 std::unordered_set<std::string>
1968     CommandObjectScriptingObjectParsed::CommandOptions::g_string_storer;
1969 
1970 // CommandObjectCommandsScriptImport
1971 #define LLDB_OPTIONS_script_import
1972 #include "CommandOptions.inc"
1973 
1974 class CommandObjectCommandsScriptImport : public CommandObjectParsed {
1975 public:
1976   CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1977       : CommandObjectParsed(interpreter, "command script import",
1978                             "Import a scripting module in LLDB.", nullptr) {
1979     AddSimpleArgumentList(eArgTypeFilename, eArgRepeatPlus);
1980   }
1981 
1982   ~CommandObjectCommandsScriptImport() override = default;
1983 
1984   Options *GetOptions() override { return &m_options; }
1985 
1986 protected:
1987   class CommandOptions : public Options {
1988   public:
1989     CommandOptions() = default;
1990 
1991     ~CommandOptions() override = default;
1992 
1993     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1994                           ExecutionContext *execution_context) override {
1995       Status error;
1996       const int short_option = m_getopt_table[option_idx].val;
1997 
1998       switch (short_option) {
1999       case 'r':
2000         // NO-OP
2001         break;
2002       case 'c':
2003         relative_to_command_file = true;
2004         break;
2005       case 's':
2006         silent = true;
2007         break;
2008       default:
2009         llvm_unreachable("Unimplemented option");
2010       }
2011 
2012       return error;
2013     }
2014 
2015     void OptionParsingStarting(ExecutionContext *execution_context) override {
2016       relative_to_command_file = false;
2017     }
2018 
2019     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2020       return llvm::ArrayRef(g_script_import_options);
2021     }
2022     bool relative_to_command_file = false;
2023     bool silent = false;
2024   };
2025 
2026   void DoExecute(Args &command, CommandReturnObject &result) override {
2027     if (command.empty()) {
2028       result.AppendError("command script import needs one or more arguments");
2029       return;
2030     }
2031 
2032     FileSpec source_dir = {};
2033     if (m_options.relative_to_command_file) {
2034       source_dir = GetDebugger().GetCommandInterpreter().GetCurrentSourceDir();
2035       if (!source_dir) {
2036         result.AppendError("command script import -c can only be specified "
2037                            "from a command file");
2038         return;
2039       }
2040     }
2041 
2042     for (auto &entry : command.entries()) {
2043       Status error;
2044 
2045       LoadScriptOptions options;
2046       options.SetInitSession(true);
2047       options.SetSilent(m_options.silent);
2048 
2049       // FIXME: this is necessary because CommandObject::CheckRequirements()
2050       // assumes that commands won't ever be recursively invoked, but it's
2051       // actually possible to craft a Python script that does other "command
2052       // script imports" in __lldb_init_module the real fix is to have
2053       // recursive commands possible with a CommandInvocation object separate
2054       // from the CommandObject itself, so that recursive command invocations
2055       // won't stomp on each other (wrt to execution contents, options, and
2056       // more)
2057       m_exe_ctx.Clear();
2058       if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule(
2059               entry.c_str(), options, error, /*module_sp=*/nullptr,
2060               source_dir)) {
2061         result.SetStatus(eReturnStatusSuccessFinishNoResult);
2062       } else {
2063         result.AppendErrorWithFormat("module importing failed: %s",
2064                                      error.AsCString());
2065       }
2066     }
2067   }
2068 
2069   CommandOptions m_options;
2070 };
2071 
2072 #define LLDB_OPTIONS_script_add
2073 #include "CommandOptions.inc"
2074 
2075 class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
2076                                        public IOHandlerDelegateMultiline {
2077 public:
2078   CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
2079       : CommandObjectParsed(interpreter, "command script add",
2080                             "Add a scripted function as an LLDB command.",
2081                             "Add a scripted function as an lldb command. "
2082                             "If you provide a single argument, the command "
2083                             "will be added at the root level of the command "
2084                             "hierarchy.  If there are more arguments they "
2085                             "must be a path to a user-added container "
2086                             "command, and the last element will be the new "
2087                             "command name."),
2088         IOHandlerDelegateMultiline("DONE") {
2089     AddSimpleArgumentList(eArgTypeCommand, eArgRepeatPlus);
2090   }
2091 
2092   ~CommandObjectCommandsScriptAdd() override = default;
2093 
2094   Options *GetOptions() override { return &m_options; }
2095 
2096   void
2097   HandleArgumentCompletion(CompletionRequest &request,
2098                            OptionElementVector &opt_element_vector) override {
2099     CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request,
2100                                                       opt_element_vector);
2101   }
2102 
2103 protected:
2104   class CommandOptions : public Options {
2105   public:
2106     CommandOptions() = default;
2107 
2108     ~CommandOptions() override = default;
2109 
2110     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2111                           ExecutionContext *execution_context) override {
2112       Status error;
2113       const int short_option = m_getopt_table[option_idx].val;
2114 
2115       switch (short_option) {
2116       case 'f':
2117         if (!option_arg.empty())
2118           m_funct_name = std::string(option_arg);
2119         break;
2120       case 'c':
2121         if (!option_arg.empty())
2122           m_class_name = std::string(option_arg);
2123         break;
2124       case 'h':
2125         if (!option_arg.empty())
2126           m_short_help = std::string(option_arg);
2127         break;
2128       case 'o':
2129         m_overwrite_lazy = eLazyBoolYes;
2130         break;
2131       case 'p':
2132         m_parsed_command = true;
2133         break;
2134       case 's':
2135         m_synchronicity =
2136             (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum(
2137                 option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
2138         if (!error.Success())
2139           return Status::FromErrorStringWithFormat(
2140               "unrecognized value for synchronicity '%s'",
2141               option_arg.str().c_str());
2142         break;
2143       case 'C': {
2144         Status error;
2145         OptionDefinition definition = GetDefinitions()[option_idx];
2146         lldb::CompletionType completion_type =
2147             static_cast<lldb::CompletionType>(OptionArgParser::ToOptionEnum(
2148                 option_arg, definition.enum_values, eNoCompletion, error));
2149         if (!error.Success())
2150           return Status::FromErrorStringWithFormat(
2151               "unrecognized value for command completion type '%s'",
2152               option_arg.str().c_str());
2153         m_completion_type = completion_type;
2154       } break;
2155       default:
2156         llvm_unreachable("Unimplemented option");
2157       }
2158 
2159       return error;
2160     }
2161 
2162     void OptionParsingStarting(ExecutionContext *execution_context) override {
2163       m_class_name.clear();
2164       m_funct_name.clear();
2165       m_short_help.clear();
2166       m_completion_type = eNoCompletion;
2167       m_overwrite_lazy = eLazyBoolCalculate;
2168       m_synchronicity = eScriptedCommandSynchronicitySynchronous;
2169       m_parsed_command = false;
2170     }
2171 
2172     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2173       return llvm::ArrayRef(g_script_add_options);
2174     }
2175 
2176     // Instance variables to hold the values for command options.
2177 
2178     std::string m_class_name;
2179     std::string m_funct_name;
2180     std::string m_short_help;
2181     LazyBool m_overwrite_lazy = eLazyBoolCalculate;
2182     ScriptedCommandSynchronicity m_synchronicity =
2183         eScriptedCommandSynchronicitySynchronous;
2184     CompletionType m_completion_type = eNoCompletion;
2185     bool m_parsed_command = false;
2186   };
2187 
2188   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
2189     StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
2190     if (output_sp && interactive) {
2191       output_sp->PutCString(g_python_command_instructions);
2192       output_sp->Flush();
2193     }
2194   }
2195 
2196   void IOHandlerInputComplete(IOHandler &io_handler,
2197                               std::string &data) override {
2198     StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
2199 
2200     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
2201     if (interpreter) {
2202       StringList lines;
2203       lines.SplitIntoLines(data);
2204       if (lines.GetSize() > 0) {
2205         std::string funct_name_str;
2206         if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
2207           if (funct_name_str.empty()) {
2208             error_sp->Printf("error: unable to obtain a function name, didn't "
2209                              "add python command.\n");
2210             error_sp->Flush();
2211           } else {
2212             // everything should be fine now, let's add this alias
2213 
2214             CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
2215                 m_interpreter, m_cmd_name, funct_name_str, m_short_help,
2216                 m_synchronicity, m_completion_type));
2217             if (!m_container) {
2218               Status error = m_interpreter.AddUserCommand(
2219                   m_cmd_name, command_obj_sp, m_overwrite);
2220               if (error.Fail()) {
2221                 error_sp->Printf("error: unable to add selected command: '%s'",
2222                                  error.AsCString());
2223                 error_sp->Flush();
2224               }
2225             } else {
2226               llvm::Error llvm_error = m_container->LoadUserSubcommand(
2227                   m_cmd_name, command_obj_sp, m_overwrite);
2228               if (llvm_error) {
2229                 error_sp->Printf("error: unable to add selected command: '%s'",
2230                                llvm::toString(std::move(llvm_error)).c_str());
2231                 error_sp->Flush();
2232               }
2233             }
2234           }
2235         } else {
2236           error_sp->Printf(
2237               "error: unable to create function, didn't add python command\n");
2238           error_sp->Flush();
2239         }
2240       } else {
2241         error_sp->Printf("error: empty function, didn't add python command\n");
2242         error_sp->Flush();
2243       }
2244     } else {
2245       error_sp->Printf(
2246           "error: script interpreter missing, didn't add python command\n");
2247       error_sp->Flush();
2248     }
2249 
2250     io_handler.SetIsDone(true);
2251   }
2252 
2253   void DoExecute(Args &command, CommandReturnObject &result) override {
2254     if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) {
2255       result.AppendError("only scripting language supported for scripted "
2256                          "commands is currently Python");
2257       return;
2258     }
2259 
2260     if (command.GetArgumentCount() == 0) {
2261       result.AppendError("'command script add' requires at least one argument");
2262       return;
2263     }
2264     // Store the options in case we get multi-line input, also figure out the
2265     // default if not user supplied:
2266     switch (m_options.m_overwrite_lazy) {
2267       case eLazyBoolCalculate:
2268         m_overwrite = !GetDebugger().GetCommandInterpreter().GetRequireCommandOverwrite();
2269         break;
2270       case eLazyBoolYes:
2271         m_overwrite = true;
2272         break;
2273       case eLazyBoolNo:
2274         m_overwrite = false;
2275     }
2276 
2277     Status path_error;
2278     m_container = GetCommandInterpreter().VerifyUserMultiwordCmdPath(
2279         command, true, path_error);
2280 
2281     if (path_error.Fail()) {
2282       result.AppendErrorWithFormat("error in command path: %s",
2283                                    path_error.AsCString());
2284       return;
2285     }
2286 
2287     if (!m_container) {
2288       // This is getting inserted into the root of the interpreter.
2289       m_cmd_name = std::string(command[0].ref());
2290     } else {
2291       size_t num_args = command.GetArgumentCount();
2292       m_cmd_name = std::string(command[num_args - 1].ref());
2293     }
2294 
2295     m_short_help.assign(m_options.m_short_help);
2296     m_synchronicity = m_options.m_synchronicity;
2297     m_completion_type = m_options.m_completion_type;
2298 
2299     // Handle the case where we prompt for the script code first:
2300     if (m_options.m_class_name.empty() && m_options.m_funct_name.empty()) {
2301       m_interpreter.GetPythonCommandsFromIOHandler("     ", // Prompt
2302                                                    *this);  // IOHandlerDelegate
2303       return;
2304     }
2305 
2306     CommandObjectSP new_cmd_sp;
2307     if (m_options.m_class_name.empty()) {
2308       new_cmd_sp.reset(new CommandObjectPythonFunction(
2309           m_interpreter, m_cmd_name, m_options.m_funct_name,
2310           m_options.m_short_help, m_synchronicity, m_completion_type));
2311     } else {
2312       ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
2313       if (!interpreter) {
2314         result.AppendError("cannot find ScriptInterpreter");
2315         return;
2316       }
2317 
2318       auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
2319           m_options.m_class_name.c_str());
2320       if (!cmd_obj_sp) {
2321         result.AppendErrorWithFormatv("cannot create helper object for: "
2322                                       "'{0}'", m_options.m_class_name);
2323         return;
2324       }
2325 
2326       if (m_options.m_parsed_command) {
2327         new_cmd_sp = CommandObjectScriptingObjectParsed::Create(m_interpreter,
2328             m_cmd_name, cmd_obj_sp, m_synchronicity, result);
2329         if (!result.Succeeded())
2330           return;
2331       } else
2332         new_cmd_sp.reset(new CommandObjectScriptingObjectRaw(
2333             m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity,
2334             m_completion_type));
2335     }
2336 
2337     // Assume we're going to succeed...
2338     result.SetStatus(eReturnStatusSuccessFinishNoResult);
2339     if (!m_container) {
2340       Status add_error =
2341           m_interpreter.AddUserCommand(m_cmd_name, new_cmd_sp, m_overwrite);
2342       if (add_error.Fail())
2343         result.AppendErrorWithFormat("cannot add command: %s",
2344                                      add_error.AsCString());
2345     } else {
2346       llvm::Error llvm_error =
2347           m_container->LoadUserSubcommand(m_cmd_name, new_cmd_sp, m_overwrite);
2348       if (llvm_error)
2349         result.AppendErrorWithFormat(
2350             "cannot add command: %s",
2351             llvm::toString(std::move(llvm_error)).c_str());
2352     }
2353   }
2354 
2355   CommandOptions m_options;
2356   std::string m_cmd_name;
2357   CommandObjectMultiword *m_container = nullptr;
2358   std::string m_short_help;
2359   bool m_overwrite = false;
2360   ScriptedCommandSynchronicity m_synchronicity =
2361       eScriptedCommandSynchronicitySynchronous;
2362   CompletionType m_completion_type = eNoCompletion;
2363 };
2364 
2365 // CommandObjectCommandsScriptList
2366 
2367 class CommandObjectCommandsScriptList : public CommandObjectParsed {
2368 public:
2369   CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
2370       : CommandObjectParsed(interpreter, "command script list",
2371                             "List defined top-level scripted commands.",
2372                             nullptr) {}
2373 
2374   ~CommandObjectCommandsScriptList() override = default;
2375 
2376   void DoExecute(Args &command, CommandReturnObject &result) override {
2377     m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
2378 
2379     result.SetStatus(eReturnStatusSuccessFinishResult);
2380   }
2381 };
2382 
2383 // CommandObjectCommandsScriptClear
2384 
2385 class CommandObjectCommandsScriptClear : public CommandObjectParsed {
2386 public:
2387   CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
2388       : CommandObjectParsed(interpreter, "command script clear",
2389                             "Delete all scripted commands.", nullptr) {}
2390 
2391   ~CommandObjectCommandsScriptClear() override = default;
2392 
2393 protected:
2394   void DoExecute(Args &command, CommandReturnObject &result) override {
2395     m_interpreter.RemoveAllUser();
2396 
2397     result.SetStatus(eReturnStatusSuccessFinishResult);
2398   }
2399 };
2400 
2401 // CommandObjectCommandsScriptDelete
2402 
2403 class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
2404 public:
2405   CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
2406       : CommandObjectParsed(
2407             interpreter, "command script delete",
2408             "Delete a scripted command by specifying the path to the command.",
2409             nullptr) {
2410     AddSimpleArgumentList(eArgTypeCommand, eArgRepeatPlus);
2411   }
2412 
2413   ~CommandObjectCommandsScriptDelete() override = default;
2414 
2415   void
2416   HandleArgumentCompletion(CompletionRequest &request,
2417                            OptionElementVector &opt_element_vector) override {
2418     lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs(
2419         m_interpreter, request, opt_element_vector);
2420   }
2421 
2422 protected:
2423   void DoExecute(Args &command, CommandReturnObject &result) override {
2424 
2425     llvm::StringRef root_cmd = command[0].ref();
2426     size_t num_args = command.GetArgumentCount();
2427 
2428     if (root_cmd.empty()) {
2429       result.AppendErrorWithFormat("empty root command name");
2430       return;
2431     }
2432     if (!m_interpreter.HasUserCommands() &&
2433         !m_interpreter.HasUserMultiwordCommands()) {
2434       result.AppendErrorWithFormat("can only delete user defined commands, "
2435                                    "but no user defined commands found");
2436       return;
2437     }
2438 
2439     CommandObjectSP cmd_sp = m_interpreter.GetCommandSPExact(root_cmd);
2440     if (!cmd_sp) {
2441       result.AppendErrorWithFormat("command '%s' not found.",
2442                                    command[0].c_str());
2443       return;
2444     }
2445     if (!cmd_sp->IsUserCommand()) {
2446       result.AppendErrorWithFormat("command '%s' is not a user command.",
2447                                    command[0].c_str());
2448       return;
2449     }
2450     if (cmd_sp->GetAsMultiwordCommand() && num_args == 1) {
2451       result.AppendErrorWithFormat("command '%s' is a multi-word command.\n "
2452                                    "Delete with \"command container delete\"",
2453                                    command[0].c_str());
2454       return;
2455     }
2456 
2457     if (command.GetArgumentCount() == 1) {
2458       m_interpreter.RemoveUser(root_cmd);
2459       result.SetStatus(eReturnStatusSuccessFinishResult);
2460       return;
2461     }
2462     // We're deleting a command from a multiword command.  Verify the command
2463     // path:
2464     Status error;
2465     CommandObjectMultiword *container =
2466         GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
2467                                                            error);
2468     if (error.Fail()) {
2469       result.AppendErrorWithFormat("could not resolve command path: %s",
2470                                    error.AsCString());
2471       return;
2472     }
2473     if (!container) {
2474       // This means that command only had a leaf command, so the container is
2475       // the root.  That should have been handled above.
2476       result.AppendErrorWithFormat("could not find a container for '%s'",
2477                                    command[0].c_str());
2478       return;
2479     }
2480     const char *leaf_cmd = command[num_args - 1].c_str();
2481     llvm::Error llvm_error =
2482         container->RemoveUserSubcommand(leaf_cmd,
2483                                         /* multiword not okay */ false);
2484     if (llvm_error) {
2485       result.AppendErrorWithFormat(
2486           "could not delete command '%s': %s", leaf_cmd,
2487           llvm::toString(std::move(llvm_error)).c_str());
2488       return;
2489     }
2490 
2491     Stream &out_stream = result.GetOutputStream();
2492 
2493     out_stream << "Deleted command:";
2494     for (size_t idx = 0; idx < num_args; idx++) {
2495       out_stream << ' ';
2496       out_stream << command[idx].c_str();
2497     }
2498     out_stream << '\n';
2499     result.SetStatus(eReturnStatusSuccessFinishResult);
2500   }
2501 };
2502 
2503 #pragma mark CommandObjectMultiwordCommandsScript
2504 
2505 // CommandObjectMultiwordCommandsScript
2506 
2507 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
2508 public:
2509   CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
2510       : CommandObjectMultiword(
2511             interpreter, "command script",
2512             "Commands for managing custom "
2513             "commands implemented by "
2514             "interpreter scripts.",
2515             "command script <subcommand> [<subcommand-options>]") {
2516     LoadSubCommand("add", CommandObjectSP(
2517                               new CommandObjectCommandsScriptAdd(interpreter)));
2518     LoadSubCommand(
2519         "delete",
2520         CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
2521     LoadSubCommand(
2522         "clear",
2523         CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
2524     LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
2525                                interpreter)));
2526     LoadSubCommand(
2527         "import",
2528         CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
2529   }
2530 
2531   ~CommandObjectMultiwordCommandsScript() override = default;
2532 };
2533 
2534 #pragma mark CommandObjectCommandContainer
2535 #define LLDB_OPTIONS_container_add
2536 #include "CommandOptions.inc"
2537 
2538 class CommandObjectCommandsContainerAdd : public CommandObjectParsed {
2539 public:
2540   CommandObjectCommandsContainerAdd(CommandInterpreter &interpreter)
2541       : CommandObjectParsed(
2542             interpreter, "command container add",
2543             "Add a container command to lldb.  Adding to built-"
2544             "in container commands is not allowed.",
2545             "command container add [[path1]...] container-name") {
2546     AddSimpleArgumentList(eArgTypeCommand, eArgRepeatPlus);
2547   }
2548 
2549   ~CommandObjectCommandsContainerAdd() override = default;
2550 
2551   Options *GetOptions() override { return &m_options; }
2552 
2553   void
2554   HandleArgumentCompletion(CompletionRequest &request,
2555                            OptionElementVector &opt_element_vector) override {
2556     lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs(
2557         m_interpreter, request, opt_element_vector);
2558   }
2559 
2560 protected:
2561   class CommandOptions : public Options {
2562   public:
2563     CommandOptions() = default;
2564 
2565     ~CommandOptions() override = default;
2566 
2567     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2568                           ExecutionContext *execution_context) override {
2569       Status error;
2570       const int short_option = m_getopt_table[option_idx].val;
2571 
2572       switch (short_option) {
2573       case 'h':
2574         if (!option_arg.empty())
2575           m_short_help = std::string(option_arg);
2576         break;
2577       case 'o':
2578         m_overwrite = true;
2579         break;
2580       case 'H':
2581         if (!option_arg.empty())
2582           m_long_help = std::string(option_arg);
2583         break;
2584       default:
2585         llvm_unreachable("Unimplemented option");
2586       }
2587 
2588       return error;
2589     }
2590 
2591     void OptionParsingStarting(ExecutionContext *execution_context) override {
2592       m_short_help.clear();
2593       m_long_help.clear();
2594       m_overwrite = false;
2595     }
2596 
2597     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2598       return llvm::ArrayRef(g_container_add_options);
2599     }
2600 
2601     // Instance variables to hold the values for command options.
2602 
2603     std::string m_short_help;
2604     std::string m_long_help;
2605     bool m_overwrite = false;
2606   };
2607   void DoExecute(Args &command, CommandReturnObject &result) override {
2608     size_t num_args = command.GetArgumentCount();
2609 
2610     if (num_args == 0) {
2611       result.AppendError("no command was specified");
2612       return;
2613     }
2614 
2615     if (num_args == 1) {
2616       // We're adding this as a root command, so use the interpreter.
2617       const char *cmd_name = command.GetArgumentAtIndex(0);
2618       auto cmd_sp = CommandObjectSP(new CommandObjectMultiword(
2619           GetCommandInterpreter(), cmd_name, m_options.m_short_help.c_str(),
2620           m_options.m_long_help.c_str()));
2621       cmd_sp->GetAsMultiwordCommand()->SetRemovable(true);
2622       Status add_error = GetCommandInterpreter().AddUserCommand(
2623           cmd_name, cmd_sp, m_options.m_overwrite);
2624       if (add_error.Fail()) {
2625         result.AppendErrorWithFormat("error adding command: %s",
2626                                      add_error.AsCString());
2627         return;
2628       }
2629       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2630       return;
2631     }
2632 
2633     // We're adding this to a subcommand, first find the subcommand:
2634     Status path_error;
2635     CommandObjectMultiword *add_to_me =
2636         GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
2637                                                            path_error);
2638 
2639     if (!add_to_me) {
2640       result.AppendErrorWithFormat("error adding command: %s",
2641                                    path_error.AsCString());
2642       return;
2643     }
2644 
2645     const char *cmd_name = command.GetArgumentAtIndex(num_args - 1);
2646     auto cmd_sp = CommandObjectSP(new CommandObjectMultiword(
2647         GetCommandInterpreter(), cmd_name, m_options.m_short_help.c_str(),
2648         m_options.m_long_help.c_str()));
2649     llvm::Error llvm_error =
2650         add_to_me->LoadUserSubcommand(cmd_name, cmd_sp, m_options.m_overwrite);
2651     if (llvm_error) {
2652       result.AppendErrorWithFormat("error adding subcommand: %s",
2653                                    llvm::toString(std::move(llvm_error)).c_str());
2654       return;
2655     }
2656 
2657     result.SetStatus(eReturnStatusSuccessFinishNoResult);
2658   }
2659 
2660 private:
2661   CommandOptions m_options;
2662 };
2663 
2664 #define LLDB_OPTIONS_multiword_delete
2665 #include "CommandOptions.inc"
2666 class CommandObjectCommandsContainerDelete : public CommandObjectParsed {
2667 public:
2668   CommandObjectCommandsContainerDelete(CommandInterpreter &interpreter)
2669       : CommandObjectParsed(
2670             interpreter, "command container delete",
2671             "Delete a container command previously added to "
2672             "lldb.",
2673             "command container delete [[path1] ...] container-cmd") {
2674     AddSimpleArgumentList(eArgTypeCommand, eArgRepeatPlus);
2675   }
2676 
2677   ~CommandObjectCommandsContainerDelete() override = default;
2678 
2679   void
2680   HandleArgumentCompletion(CompletionRequest &request,
2681                            OptionElementVector &opt_element_vector) override {
2682     lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs(
2683         m_interpreter, request, opt_element_vector);
2684   }
2685 
2686 protected:
2687   void DoExecute(Args &command, CommandReturnObject &result) override {
2688     size_t num_args = command.GetArgumentCount();
2689 
2690     if (num_args == 0) {
2691       result.AppendError("No command was specified.");
2692       return;
2693     }
2694 
2695     if (num_args == 1) {
2696       // We're removing a root command, so we need to delete it from the
2697       // interpreter.
2698       const char *cmd_name = command.GetArgumentAtIndex(0);
2699       // Let's do a little more work here so we can do better error reporting.
2700       CommandInterpreter &interp = GetCommandInterpreter();
2701       CommandObjectSP cmd_sp = interp.GetCommandSPExact(cmd_name);
2702       if (!cmd_sp) {
2703         result.AppendErrorWithFormat("container command %s doesn't exist.",
2704                                      cmd_name);
2705         return;
2706       }
2707       if (!cmd_sp->IsUserCommand()) {
2708         result.AppendErrorWithFormat(
2709             "container command %s is not a user command", cmd_name);
2710         return;
2711       }
2712       if (!cmd_sp->GetAsMultiwordCommand()) {
2713         result.AppendErrorWithFormat("command %s is not a container command",
2714                                      cmd_name);
2715         return;
2716       }
2717 
2718       bool did_remove = GetCommandInterpreter().RemoveUserMultiword(cmd_name);
2719       if (!did_remove) {
2720         result.AppendErrorWithFormat("error removing command %s.", cmd_name);
2721         return;
2722       }
2723 
2724       result.SetStatus(eReturnStatusSuccessFinishNoResult);
2725       return;
2726     }
2727 
2728     // We're removing a subcommand, first find the subcommand's owner:
2729     Status path_error;
2730     CommandObjectMultiword *container =
2731         GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true,
2732                                                            path_error);
2733 
2734     if (!container) {
2735       result.AppendErrorWithFormat("error removing container command: %s",
2736                                    path_error.AsCString());
2737       return;
2738     }
2739     const char *leaf = command.GetArgumentAtIndex(num_args - 1);
2740     llvm::Error llvm_error =
2741         container->RemoveUserSubcommand(leaf, /* multiword okay */ true);
2742     if (llvm_error) {
2743       result.AppendErrorWithFormat("error removing container command: %s",
2744                                    llvm::toString(std::move(llvm_error)).c_str());
2745       return;
2746     }
2747     result.SetStatus(eReturnStatusSuccessFinishNoResult);
2748   }
2749 };
2750 
2751 class CommandObjectCommandContainer : public CommandObjectMultiword {
2752 public:
2753   CommandObjectCommandContainer(CommandInterpreter &interpreter)
2754       : CommandObjectMultiword(
2755             interpreter, "command container",
2756             "Commands for adding container commands to lldb.  "
2757             "Container commands are containers for other commands.  You can "
2758             "add nested container commands by specifying a command path, "
2759             "but you can't add commands into the built-in command hierarchy.",
2760             "command container <subcommand> [<subcommand-options>]") {
2761     LoadSubCommand("add", CommandObjectSP(new CommandObjectCommandsContainerAdd(
2762                               interpreter)));
2763     LoadSubCommand(
2764         "delete",
2765         CommandObjectSP(new CommandObjectCommandsContainerDelete(interpreter)));
2766   }
2767 
2768   ~CommandObjectCommandContainer() override = default;
2769 };
2770 
2771 #pragma mark CommandObjectMultiwordCommands
2772 
2773 // CommandObjectMultiwordCommands
2774 
2775 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
2776     CommandInterpreter &interpreter)
2777     : CommandObjectMultiword(interpreter, "command",
2778                              "Commands for managing custom LLDB commands.",
2779                              "command <subcommand> [<subcommand-options>]") {
2780   LoadSubCommand("source",
2781                  CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
2782   LoadSubCommand("alias",
2783                  CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
2784   LoadSubCommand("unalias", CommandObjectSP(
2785                                 new CommandObjectCommandsUnalias(interpreter)));
2786   LoadSubCommand("delete",
2787                  CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
2788   LoadSubCommand("container", CommandObjectSP(new CommandObjectCommandContainer(
2789                                   interpreter)));
2790   LoadSubCommand(
2791       "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
2792   LoadSubCommand(
2793       "script",
2794       CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
2795 }
2796 
2797 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
2798