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