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