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