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/CommandReturnObject.h"
17 #include "lldb/Interpreter/OptionArgParser.h"
18 #include "lldb/Interpreter/OptionValueBoolean.h"
19 #include "lldb/Interpreter/OptionValueString.h"
20 #include "lldb/Interpreter/OptionValueUInt64.h"
21 #include "lldb/Interpreter/Options.h"
22 #include "lldb/Interpreter/ScriptInterpreter.h"
23 #include "lldb/Utility/Args.h"
24 #include "lldb/Utility/StringList.h"
25 #include "llvm/ADT/StringRef.h"
26 
27 using namespace lldb;
28 using namespace lldb_private;
29 
30 // CommandObjectCommandsSource
31 
32 #define LLDB_OPTIONS_source
33 #include "CommandOptions.inc"
34 
35 class CommandObjectCommandsSource : public CommandObjectParsed {
36 public:
37   CommandObjectCommandsSource(CommandInterpreter &interpreter)
38       : CommandObjectParsed(
39             interpreter, "command source",
40             "Read and execute LLDB commands from the file <filename>.",
41             nullptr),
42         m_options() {
43     CommandArgumentEntry arg;
44     CommandArgumentData file_arg;
45 
46     // Define the first (and only) variant of this arg.
47     file_arg.arg_type = eArgTypeFilename;
48     file_arg.arg_repetition = eArgRepeatPlain;
49 
50     // There is only one variant this argument could be; put it into the
51     // argument entry.
52     arg.push_back(file_arg);
53 
54     // Push the data for the first argument into the m_arguments vector.
55     m_arguments.push_back(arg);
56   }
57 
58   ~CommandObjectCommandsSource() override = default;
59 
60   const char *GetRepeatCommand(Args &current_command_args,
61                                uint32_t index) override {
62     return "";
63   }
64 
65   void
66   HandleArgumentCompletion(CompletionRequest &request,
67                            OptionElementVector &opt_element_vector) override {
68     CommandCompletions::InvokeCommonCompletionCallbacks(
69         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
70         request, nullptr);
71   }
72 
73   Options *GetOptions() override { return &m_options; }
74 
75 protected:
76   class CommandOptions : public Options {
77   public:
78     CommandOptions()
79         : Options(), m_stop_on_error(true), m_silent_run(false),
80           m_stop_on_continue(true) {}
81 
82     ~CommandOptions() override = default;
83 
84     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
85                           ExecutionContext *execution_context) override {
86       Status error;
87       const int short_option = m_getopt_table[option_idx].val;
88 
89       switch (short_option) {
90       case 'e':
91         error = m_stop_on_error.SetValueFromString(option_arg);
92         break;
93 
94       case 'c':
95         error = m_stop_on_continue.SetValueFromString(option_arg);
96         break;
97 
98       case 's':
99         error = m_silent_run.SetValueFromString(option_arg);
100         break;
101 
102       default:
103         llvm_unreachable("Unimplemented option");
104       }
105 
106       return error;
107     }
108 
109     void OptionParsingStarting(ExecutionContext *execution_context) override {
110       m_stop_on_error.Clear();
111       m_silent_run.Clear();
112       m_stop_on_continue.Clear();
113     }
114 
115     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
116       return llvm::makeArrayRef(g_source_options);
117     }
118 
119     // Instance variables to hold the values for command options.
120 
121     OptionValueBoolean m_stop_on_error;
122     OptionValueBoolean m_silent_run;
123     OptionValueBoolean m_stop_on_continue;
124   };
125 
126   bool DoExecute(Args &command, CommandReturnObject &result) override {
127     if (command.GetArgumentCount() != 1) {
128       result.AppendErrorWithFormat(
129           "'%s' takes exactly one executable filename argument.\n",
130           GetCommandName().str().c_str());
131       result.SetStatus(eReturnStatusFailed);
132       return false;
133     }
134 
135     FileSpec cmd_file(command[0].ref());
136     FileSystem::Instance().Resolve(cmd_file);
137 
138     CommandInterpreterRunOptions options;
139     // If any options were set, then use them
140     if (m_options.m_stop_on_error.OptionWasSet() ||
141         m_options.m_silent_run.OptionWasSet() ||
142         m_options.m_stop_on_continue.OptionWasSet()) {
143       if (m_options.m_stop_on_continue.OptionWasSet())
144         options.SetStopOnContinue(
145             m_options.m_stop_on_continue.GetCurrentValue());
146 
147       if (m_options.m_stop_on_error.OptionWasSet())
148         options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue());
149 
150       // Individual silent setting is override for global command echo settings.
151       if (m_options.m_silent_run.GetCurrentValue()) {
152         options.SetSilent(true);
153       } else {
154         options.SetPrintResults(true);
155         options.SetPrintErrors(true);
156         options.SetEchoCommands(m_interpreter.GetEchoCommands());
157         options.SetEchoCommentCommands(m_interpreter.GetEchoCommentCommands());
158       }
159     }
160 
161     m_interpreter.HandleCommandsFromFile(cmd_file, options, result);
162     return result.Succeeded();
163   }
164 
165   CommandOptions m_options;
166 };
167 
168 #pragma mark CommandObjectCommandsAlias
169 // CommandObjectCommandsAlias
170 
171 #define LLDB_OPTIONS_alias
172 #include "CommandOptions.inc"
173 
174 static const char *g_python_command_instructions =
175     "Enter your Python command(s). Type 'DONE' to end.\n"
176     "You must define a Python function with this signature:\n"
177     "def my_command_impl(debugger, args, result, internal_dict):\n";
178 
179 class CommandObjectCommandsAlias : public CommandObjectRaw {
180 protected:
181   class CommandOptions : public OptionGroup {
182   public:
183     CommandOptions() : OptionGroup(), m_help(), m_long_help() {}
184 
185     ~CommandOptions() override = default;
186 
187     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
188       return llvm::makeArrayRef(g_alias_options);
189     }
190 
191     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
192                           ExecutionContext *execution_context) override {
193       Status error;
194 
195       const int short_option = GetDefinitions()[option_idx].short_option;
196       std::string option_str(option_value);
197 
198       switch (short_option) {
199       case 'h':
200         m_help.SetCurrentValue(option_str);
201         m_help.SetOptionWasSet();
202         break;
203 
204       case 'H':
205         m_long_help.SetCurrentValue(option_str);
206         m_long_help.SetOptionWasSet();
207         break;
208 
209       default:
210         llvm_unreachable("Unimplemented option");
211       }
212 
213       return error;
214     }
215 
216     void OptionParsingStarting(ExecutionContext *execution_context) override {
217       m_help.Clear();
218       m_long_help.Clear();
219     }
220 
221     OptionValueString m_help;
222     OptionValueString m_long_help;
223   };
224 
225   OptionGroupOptions m_option_group;
226   CommandOptions m_command_options;
227 
228 public:
229   Options *GetOptions() override { return &m_option_group; }
230 
231   CommandObjectCommandsAlias(CommandInterpreter &interpreter)
232       : CommandObjectRaw(
233             interpreter, "command alias",
234             "Define a custom command in terms of an existing command."),
235         m_option_group(), m_command_options() {
236     m_option_group.Append(&m_command_options);
237     m_option_group.Finalize();
238 
239     SetHelpLong(
240         "'alias' allows the user to create a short-cut or abbreviation for long \
241 commands, multi-word commands, and commands that take particular options.  \
242 Below are some simple examples of how one might use the 'alias' command:"
243         R"(
244 
245 (lldb) command alias sc script
246 
247     Creates the abbreviation 'sc' for the 'script' command.
248 
249 (lldb) command alias bp breakpoint
250 
251 )"
252         "    Creates the abbreviation 'bp' for the 'breakpoint' command.  Since \
253 breakpoint commands are two-word commands, the user would still need to \
254 enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
255         R"(
256 
257 (lldb) command alias bpl breakpoint list
258 
259     Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
260 
261 )"
262         "An alias can include some options for the command, with the values either \
263 filled in at the time the alias is created, or specified as positional \
264 arguments, to be filled in when the alias is invoked.  The following example \
265 shows how to create aliases with options:"
266         R"(
267 
268 (lldb) command alias bfl breakpoint set -f %1 -l %2
269 
270 )"
271         "    Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
272 options already part of the alias.  So if the user wants to set a breakpoint \
273 by file and line without explicitly having to use the -f and -l options, the \
274 user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \
275 for the actual arguments that will be passed when the alias command is used.  \
276 The number in the placeholder refers to the position/order the actual value \
277 occupies when the alias is used.  All the occurrences of '%1' in the alias \
278 will be replaced with the first argument, all the occurrences of '%2' in the \
279 alias will be replaced with the second argument, and so on.  This also allows \
280 actual arguments to be used multiple times within an alias (see 'process \
281 launch' example below)."
282         R"(
283 
284 )"
285         "Note: the positional arguments must substitute as whole words in the resultant \
286 command, so you can't at present do something like this to append the file extension \
287 \".cpp\":"
288         R"(
289 
290 (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
291 
292 )"
293         "For more complex aliasing, use the \"command regex\" command instead.  In the \
294 'bfl' case above, the actual file value will be filled in with the first argument \
295 following 'bfl' and the actual line number value will be filled in with the second \
296 argument.  The user would use this alias as follows:"
297         R"(
298 
299 (lldb) command alias bfl breakpoint set -f %1 -l %2
300 (lldb) bfl my-file.c 137
301 
302 This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
303 
304 Another example:
305 
306 (lldb) command alias pltty process launch -s -o %1 -e %1
307 (lldb) pltty /dev/tty0
308 
309     Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
310 
311 )"
312         "If the user always wanted to pass the same value to a particular option, the \
313 alias could be defined with that value directly in the alias as a constant, \
314 rather than using a positional placeholder:"
315         R"(
316 
317 (lldb) command alias bl3 breakpoint set -f %1 -l 3
318 
319     Always sets a breakpoint on line 3 of whatever file is indicated.)");
320 
321     CommandArgumentEntry arg1;
322     CommandArgumentEntry arg2;
323     CommandArgumentEntry arg3;
324     CommandArgumentData alias_arg;
325     CommandArgumentData cmd_arg;
326     CommandArgumentData options_arg;
327 
328     // Define the first (and only) variant of this arg.
329     alias_arg.arg_type = eArgTypeAliasName;
330     alias_arg.arg_repetition = eArgRepeatPlain;
331 
332     // There is only one variant this argument could be; put it into the
333     // argument entry.
334     arg1.push_back(alias_arg);
335 
336     // Define the first (and only) variant of this arg.
337     cmd_arg.arg_type = eArgTypeCommandName;
338     cmd_arg.arg_repetition = eArgRepeatPlain;
339 
340     // There is only one variant this argument could be; put it into the
341     // argument entry.
342     arg2.push_back(cmd_arg);
343 
344     // Define the first (and only) variant of this arg.
345     options_arg.arg_type = eArgTypeAliasOptions;
346     options_arg.arg_repetition = eArgRepeatOptional;
347 
348     // There is only one variant this argument could be; put it into the
349     // argument entry.
350     arg3.push_back(options_arg);
351 
352     // Push the data for the first argument into the m_arguments vector.
353     m_arguments.push_back(arg1);
354     m_arguments.push_back(arg2);
355     m_arguments.push_back(arg3);
356   }
357 
358   ~CommandObjectCommandsAlias() override = default;
359 
360 protected:
361   bool DoExecute(llvm::StringRef raw_command_line,
362                  CommandReturnObject &result) override {
363     if (raw_command_line.empty()) {
364       result.AppendError("'command alias' requires at least two arguments");
365       return false;
366     }
367 
368     ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
369     m_option_group.NotifyOptionParsingStarting(&exe_ctx);
370 
371     OptionsWithRaw args_with_suffix(raw_command_line);
372 
373     if (args_with_suffix.HasArgs())
374       if (!ParseOptionsAndNotify(args_with_suffix.GetArgs(), result,
375                                  m_option_group, exe_ctx))
376         return false;
377 
378     llvm::StringRef raw_command_string = args_with_suffix.GetRawPart();
379     Args args(raw_command_string);
380 
381     if (args.GetArgumentCount() < 2) {
382       result.AppendError("'command alias' requires at least two arguments");
383       result.SetStatus(eReturnStatusFailed);
384       return false;
385     }
386 
387     // Get the alias command.
388 
389     auto alias_command = args[0].ref();
390     if (alias_command.startswith("-")) {
391       result.AppendError("aliases starting with a dash are not supported");
392       if (alias_command == "--help" || alias_command == "--long-help") {
393         result.AppendWarning("if trying to pass options to 'command alias' add "
394                              "a -- at the end of the options");
395       }
396       result.SetStatus(eReturnStatusFailed);
397       return false;
398     }
399 
400     // Strip the new alias name off 'raw_command_string'  (leave it on args,
401     // which gets passed to 'Execute', which does the stripping itself.
402     size_t pos = raw_command_string.find(alias_command);
403     if (pos == 0) {
404       raw_command_string = raw_command_string.substr(alias_command.size());
405       pos = raw_command_string.find_first_not_of(' ');
406       if ((pos != std::string::npos) && (pos > 0))
407         raw_command_string = raw_command_string.substr(pos);
408     } else {
409       result.AppendError("Error parsing command string.  No alias created.");
410       result.SetStatus(eReturnStatusFailed);
411       return false;
412     }
413 
414     // Verify that the command is alias-able.
415     if (m_interpreter.CommandExists(alias_command)) {
416       result.AppendErrorWithFormat(
417           "'%s' is a permanent debugger command and cannot be redefined.\n",
418           args[0].c_str());
419       result.SetStatus(eReturnStatusFailed);
420       return false;
421     }
422 
423     // Get CommandObject that is being aliased. The command name is read from
424     // the front of raw_command_string. raw_command_string is returned with the
425     // name of the command object stripped off the front.
426     llvm::StringRef original_raw_command_string = raw_command_string;
427     CommandObject *cmd_obj =
428         m_interpreter.GetCommandObjectForCommand(raw_command_string);
429 
430     if (!cmd_obj) {
431       result.AppendErrorWithFormat("invalid command given to 'command alias'. "
432                                    "'%s' does not begin with a valid command."
433                                    "  No alias created.",
434                                    original_raw_command_string.str().c_str());
435       result.SetStatus(eReturnStatusFailed);
436       return false;
437     } else if (!cmd_obj->WantsRawCommandString()) {
438       // Note that args was initialized with the original command, and has not
439       // been updated to this point. Therefore can we pass it to the version of
440       // Execute that does not need/expect raw input in the alias.
441       return HandleAliasingNormalCommand(args, result);
442     } else {
443       return HandleAliasingRawCommand(alias_command, raw_command_string,
444                                       *cmd_obj, result);
445     }
446     return result.Succeeded();
447   }
448 
449   bool HandleAliasingRawCommand(llvm::StringRef alias_command,
450                                 llvm::StringRef raw_command_string,
451                                 CommandObject &cmd_obj,
452                                 CommandReturnObject &result) {
453     // Verify & handle any options/arguments passed to the alias command
454 
455     OptionArgVectorSP option_arg_vector_sp =
456         OptionArgVectorSP(new OptionArgVector);
457 
458     if (CommandObjectSP cmd_obj_sp =
459             m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) {
460       if (m_interpreter.AliasExists(alias_command) ||
461           m_interpreter.UserCommandExists(alias_command)) {
462         result.AppendWarningWithFormat(
463             "Overwriting existing definition for '%s'.\n",
464             alias_command.str().c_str());
465       }
466       if (CommandAlias *alias = m_interpreter.AddAlias(
467               alias_command, cmd_obj_sp, raw_command_string)) {
468         if (m_command_options.m_help.OptionWasSet())
469           alias->SetHelp(m_command_options.m_help.GetCurrentValue());
470         if (m_command_options.m_long_help.OptionWasSet())
471           alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
472         result.SetStatus(eReturnStatusSuccessFinishNoResult);
473       } else {
474         result.AppendError("Unable to create requested alias.\n");
475         result.SetStatus(eReturnStatusFailed);
476       }
477 
478     } else {
479       result.AppendError("Unable to create requested alias.\n");
480       result.SetStatus(eReturnStatusFailed);
481     }
482 
483     return result.Succeeded();
484   }
485 
486   bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
487     size_t argc = args.GetArgumentCount();
488 
489     if (argc < 2) {
490       result.AppendError("'command alias' requires at least two arguments");
491       result.SetStatus(eReturnStatusFailed);
492       return false;
493     }
494 
495     // Save these in std::strings since we're going to shift them off.
496     const std::string alias_command(std::string(args[0].ref()));
497     const std::string actual_command(std::string(args[1].ref()));
498 
499     args.Shift(); // Shift the alias command word off the argument vector.
500     args.Shift(); // Shift the old command word off the argument vector.
501 
502     // Verify that the command is alias'able, and get the appropriate command
503     // object.
504 
505     if (m_interpreter.CommandExists(alias_command)) {
506       result.AppendErrorWithFormat(
507           "'%s' is a permanent debugger command and cannot be redefined.\n",
508           alias_command.c_str());
509       result.SetStatus(eReturnStatusFailed);
510       return false;
511     }
512 
513     CommandObjectSP command_obj_sp(
514         m_interpreter.GetCommandSPExact(actual_command, true));
515     CommandObjectSP subcommand_obj_sp;
516     bool use_subcommand = false;
517     if (!command_obj_sp) {
518       result.AppendErrorWithFormat("'%s' is not an existing command.\n",
519                                    actual_command.c_str());
520       result.SetStatus(eReturnStatusFailed);
521       return false;
522     }
523     CommandObject *cmd_obj = command_obj_sp.get();
524     CommandObject *sub_cmd_obj = nullptr;
525     OptionArgVectorSP option_arg_vector_sp =
526         OptionArgVectorSP(new OptionArgVector);
527 
528     while (cmd_obj->IsMultiwordObject() && !args.empty()) {
529       auto sub_command = args[0].ref();
530       assert(!sub_command.empty());
531       subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command);
532       if (!subcommand_obj_sp) {
533         result.AppendErrorWithFormat(
534             "'%s' is not a valid sub-command of '%s'.  "
535             "Unable to create alias.\n",
536             args[0].c_str(), actual_command.c_str());
537         result.SetStatus(eReturnStatusFailed);
538         return false;
539       }
540 
541       sub_cmd_obj = subcommand_obj_sp.get();
542       use_subcommand = true;
543       args.Shift(); // Shift the sub_command word off the argument vector.
544       cmd_obj = sub_cmd_obj;
545     }
546 
547     // Verify & handle any options/arguments passed to the alias command
548 
549     std::string args_string;
550 
551     if (!args.empty()) {
552       CommandObjectSP tmp_sp =
553           m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false);
554       if (use_subcommand)
555         tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName(),
556                                                  false);
557 
558       args.GetCommandString(args_string);
559     }
560 
561     if (m_interpreter.AliasExists(alias_command) ||
562         m_interpreter.UserCommandExists(alias_command)) {
563       result.AppendWarningWithFormat(
564           "Overwriting existing definition for '%s'.\n", alias_command.c_str());
565     }
566 
567     if (CommandAlias *alias = m_interpreter.AddAlias(
568             alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp,
569             args_string)) {
570       if (m_command_options.m_help.OptionWasSet())
571         alias->SetHelp(m_command_options.m_help.GetCurrentValue());
572       if (m_command_options.m_long_help.OptionWasSet())
573         alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
574       result.SetStatus(eReturnStatusSuccessFinishNoResult);
575     } else {
576       result.AppendError("Unable to create requested alias.\n");
577       result.SetStatus(eReturnStatusFailed);
578       return false;
579     }
580 
581     return result.Succeeded();
582   }
583 };
584 
585 #pragma mark CommandObjectCommandsUnalias
586 // CommandObjectCommandsUnalias
587 
588 class CommandObjectCommandsUnalias : public CommandObjectParsed {
589 public:
590   CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
591       : CommandObjectParsed(
592             interpreter, "command unalias",
593             "Delete one or more custom commands defined by 'command alias'.",
594             nullptr) {
595     CommandArgumentEntry arg;
596     CommandArgumentData alias_arg;
597 
598     // Define the first (and only) variant of this arg.
599     alias_arg.arg_type = eArgTypeAliasName;
600     alias_arg.arg_repetition = eArgRepeatPlain;
601 
602     // There is only one variant this argument could be; put it into the
603     // argument entry.
604     arg.push_back(alias_arg);
605 
606     // Push the data for the first argument into the m_arguments vector.
607     m_arguments.push_back(arg);
608   }
609 
610   ~CommandObjectCommandsUnalias() override = default;
611 
612   void
613   HandleArgumentCompletion(CompletionRequest &request,
614                            OptionElementVector &opt_element_vector) override {
615     if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
616       return;
617 
618     for (const auto &ent : m_interpreter.GetAliases()) {
619       request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp());
620     }
621   }
622 
623 protected:
624   bool DoExecute(Args &args, CommandReturnObject &result) override {
625     CommandObject::CommandMap::iterator pos;
626     CommandObject *cmd_obj;
627 
628     if (args.empty()) {
629       result.AppendError("must call 'unalias' with a valid alias");
630       result.SetStatus(eReturnStatusFailed);
631       return false;
632     }
633 
634     auto command_name = args[0].ref();
635     cmd_obj = m_interpreter.GetCommandObject(command_name);
636     if (!cmd_obj) {
637       result.AppendErrorWithFormat(
638           "'%s' is not a known command.\nTry 'help' to see a "
639           "current list of commands.\n",
640           args[0].c_str());
641       result.SetStatus(eReturnStatusFailed);
642       return false;
643     }
644 
645     if (m_interpreter.CommandExists(command_name)) {
646       if (cmd_obj->IsRemovable()) {
647         result.AppendErrorWithFormat(
648             "'%s' is not an alias, it is a debugger command which can be "
649             "removed using the 'command delete' command.\n",
650             args[0].c_str());
651       } else {
652         result.AppendErrorWithFormat(
653             "'%s' is a permanent debugger command and cannot be removed.\n",
654             args[0].c_str());
655       }
656       result.SetStatus(eReturnStatusFailed);
657       return false;
658     }
659 
660     if (!m_interpreter.RemoveAlias(command_name)) {
661       if (m_interpreter.AliasExists(command_name))
662         result.AppendErrorWithFormat(
663             "Error occurred while attempting to unalias '%s'.\n",
664             args[0].c_str());
665       else
666         result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
667                                      args[0].c_str());
668       result.SetStatus(eReturnStatusFailed);
669       return false;
670     }
671 
672     result.SetStatus(eReturnStatusSuccessFinishNoResult);
673     return result.Succeeded();
674   }
675 };
676 
677 #pragma mark CommandObjectCommandsDelete
678 // CommandObjectCommandsDelete
679 
680 class CommandObjectCommandsDelete : public CommandObjectParsed {
681 public:
682   CommandObjectCommandsDelete(CommandInterpreter &interpreter)
683       : CommandObjectParsed(
684             interpreter, "command delete",
685             "Delete one or more custom commands defined by 'command regex'.",
686             nullptr) {
687     CommandArgumentEntry arg;
688     CommandArgumentData alias_arg;
689 
690     // Define the first (and only) variant of this arg.
691     alias_arg.arg_type = eArgTypeCommandName;
692     alias_arg.arg_repetition = eArgRepeatPlain;
693 
694     // There is only one variant this argument could be; put it into the
695     // argument entry.
696     arg.push_back(alias_arg);
697 
698     // Push the data for the first argument into the m_arguments vector.
699     m_arguments.push_back(arg);
700   }
701 
702   ~CommandObjectCommandsDelete() override = default;
703 
704   void
705   HandleArgumentCompletion(CompletionRequest &request,
706                            OptionElementVector &opt_element_vector) override {
707     if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
708       return;
709 
710     for (const auto &ent : m_interpreter.GetCommands()) {
711       if (ent.second->IsRemovable())
712         request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp());
713     }
714   }
715 
716 protected:
717   bool DoExecute(Args &args, CommandReturnObject &result) override {
718     CommandObject::CommandMap::iterator pos;
719 
720     if (args.empty()) {
721       result.AppendErrorWithFormat("must call '%s' with one or more valid user "
722                                    "defined regular expression command names",
723                                    GetCommandName().str().c_str());
724       result.SetStatus(eReturnStatusFailed);
725       return false;
726     }
727 
728     auto command_name = args[0].ref();
729     if (!m_interpreter.CommandExists(command_name)) {
730       StreamString error_msg_stream;
731       const bool generate_upropos = true;
732       const bool generate_type_lookup = false;
733       CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
734           &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(),
735           generate_upropos, generate_type_lookup);
736       result.AppendError(error_msg_stream.GetString());
737       result.SetStatus(eReturnStatusFailed);
738       return false;
739     }
740 
741     if (!m_interpreter.RemoveCommand(command_name)) {
742       result.AppendErrorWithFormat(
743           "'%s' is a permanent debugger command and cannot be removed.\n",
744           args[0].c_str());
745       result.SetStatus(eReturnStatusFailed);
746       return false;
747     }
748 
749     result.SetStatus(eReturnStatusSuccessFinishNoResult);
750     return true;
751   }
752 };
753 
754 // CommandObjectCommandsAddRegex
755 
756 #define LLDB_OPTIONS_regex
757 #include "CommandOptions.inc"
758 
759 #pragma mark CommandObjectCommandsAddRegex
760 
761 class CommandObjectCommandsAddRegex : public CommandObjectParsed,
762                                       public IOHandlerDelegateMultiline {
763 public:
764   CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
765       : CommandObjectParsed(
766             interpreter, "command regex",
767             "Define a custom command in terms of "
768             "existing commands by matching "
769             "regular expressions.",
770             "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
771         IOHandlerDelegateMultiline("",
772                                    IOHandlerDelegate::Completion::LLDBCommand),
773         m_options() {
774     SetHelpLong(
775         R"(
776 )"
777         "This command allows the user to create powerful regular expression commands \
778 with substitutions. The regular expressions and substitutions are specified \
779 using the regular expression substitution format of:"
780         R"(
781 
782     s/<regex>/<subst>/
783 
784 )"
785         "<regex> is a regular expression that can use parenthesis to capture regular \
786 expression input and substitute the captured matches in the output using %1 \
787 for the first match, %2 for the second, and so on."
788         R"(
789 
790 )"
791         "The regular expressions can all be specified on the command line if more than \
792 one argument is provided. If just the command name is provided on the command \
793 line, then the regular expressions and substitutions can be entered on separate \
794 lines, followed by an empty line to terminate the command definition."
795         R"(
796 
797 EXAMPLES
798 
799 )"
800         "The following example will define a regular expression command named 'f' that \
801 will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
802 a number follows 'f':"
803         R"(
804 
805     (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
806   }
807 
808   ~CommandObjectCommandsAddRegex() override = default;
809 
810 protected:
811   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
812     StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
813     if (output_sp && interactive) {
814       output_sp->PutCString("Enter one or more sed substitution commands in "
815                             "the form: 's/<regex>/<subst>/'.\nTerminate the "
816                             "substitution list with an empty line.\n");
817       output_sp->Flush();
818     }
819   }
820 
821   void IOHandlerInputComplete(IOHandler &io_handler,
822                               std::string &data) override {
823     io_handler.SetIsDone(true);
824     if (m_regex_cmd_up) {
825       StringList lines;
826       if (lines.SplitIntoLines(data)) {
827         bool check_only = false;
828         for (const std::string &line : lines) {
829           Status error = AppendRegexSubstitution(line, check_only);
830           if (error.Fail()) {
831             if (!GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) {
832               StreamSP out_stream = GetDebugger().GetAsyncOutputStream();
833               out_stream->Printf("error: %s\n", error.AsCString());
834             }
835           }
836         }
837       }
838       if (m_regex_cmd_up->HasRegexEntries()) {
839         CommandObjectSP cmd_sp(m_regex_cmd_up.release());
840         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
841       }
842     }
843   }
844 
845   bool DoExecute(Args &command, CommandReturnObject &result) override {
846     const size_t argc = command.GetArgumentCount();
847     if (argc == 0) {
848       result.AppendError("usage: 'command regex <command-name> "
849                          "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
850       result.SetStatus(eReturnStatusFailed);
851       return false;
852     }
853 
854     Status error;
855     auto name = command[0].ref();
856     m_regex_cmd_up = std::make_unique<CommandObjectRegexCommand>(
857         m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0,
858         true);
859 
860     if (argc == 1) {
861       Debugger &debugger = GetDebugger();
862       bool color_prompt = debugger.GetUseColor();
863       const bool multiple_lines = true; // Get multiple lines
864       IOHandlerSP io_handler_sp(new IOHandlerEditline(
865           debugger, IOHandler::Type::Other,
866           "lldb-regex",          // Name of input reader for history
867           llvm::StringRef("> "), // Prompt
868           llvm::StringRef(),     // Continuation prompt
869           multiple_lines, color_prompt,
870           0, // Don't show line numbers
871           *this, nullptr));
872 
873       if (io_handler_sp) {
874         debugger.RunIOHandlerAsync(io_handler_sp);
875         result.SetStatus(eReturnStatusSuccessFinishNoResult);
876       }
877     } else {
878       for (auto &entry : command.entries().drop_front()) {
879         bool check_only = false;
880         error = AppendRegexSubstitution(entry.ref(), check_only);
881         if (error.Fail())
882           break;
883       }
884 
885       if (error.Success()) {
886         AddRegexCommandToInterpreter();
887       }
888     }
889     if (error.Fail()) {
890       result.AppendError(error.AsCString());
891       result.SetStatus(eReturnStatusFailed);
892     }
893 
894     return result.Succeeded();
895   }
896 
897   Status AppendRegexSubstitution(const llvm::StringRef &regex_sed,
898                                  bool check_only) {
899     Status error;
900 
901     if (!m_regex_cmd_up) {
902       error.SetErrorStringWithFormat(
903           "invalid regular expression command object for: '%.*s'",
904           (int)regex_sed.size(), regex_sed.data());
905       return error;
906     }
907 
908     size_t regex_sed_size = regex_sed.size();
909 
910     if (regex_sed_size <= 1) {
911       error.SetErrorStringWithFormat(
912           "regular expression substitution string is too short: '%.*s'",
913           (int)regex_sed.size(), regex_sed.data());
914       return error;
915     }
916 
917     if (regex_sed[0] != 's') {
918       error.SetErrorStringWithFormat("regular expression substitution string "
919                                      "doesn't start with 's': '%.*s'",
920                                      (int)regex_sed.size(), regex_sed.data());
921       return error;
922     }
923     const size_t first_separator_char_pos = 1;
924     // use the char that follows 's' as the regex separator character so we can
925     // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
926     const char separator_char = regex_sed[first_separator_char_pos];
927     const size_t second_separator_char_pos =
928         regex_sed.find(separator_char, first_separator_char_pos + 1);
929 
930     if (second_separator_char_pos == std::string::npos) {
931       error.SetErrorStringWithFormat(
932           "missing second '%c' separator char after '%.*s' in '%.*s'",
933           separator_char,
934           (int)(regex_sed.size() - first_separator_char_pos - 1),
935           regex_sed.data() + (first_separator_char_pos + 1),
936           (int)regex_sed.size(), regex_sed.data());
937       return error;
938     }
939 
940     const size_t third_separator_char_pos =
941         regex_sed.find(separator_char, second_separator_char_pos + 1);
942 
943     if (third_separator_char_pos == std::string::npos) {
944       error.SetErrorStringWithFormat(
945           "missing third '%c' separator char after '%.*s' in '%.*s'",
946           separator_char,
947           (int)(regex_sed.size() - second_separator_char_pos - 1),
948           regex_sed.data() + (second_separator_char_pos + 1),
949           (int)regex_sed.size(), regex_sed.data());
950       return error;
951     }
952 
953     if (third_separator_char_pos != regex_sed_size - 1) {
954       // Make sure that everything that follows the last regex separator char
955       if (regex_sed.find_first_not_of("\t\n\v\f\r ",
956                                       third_separator_char_pos + 1) !=
957           std::string::npos) {
958         error.SetErrorStringWithFormat(
959             "extra data found after the '%.*s' regular expression substitution "
960             "string: '%.*s'",
961             (int)third_separator_char_pos + 1, regex_sed.data(),
962             (int)(regex_sed.size() - third_separator_char_pos - 1),
963             regex_sed.data() + (third_separator_char_pos + 1));
964         return error;
965       }
966     } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
967       error.SetErrorStringWithFormat(
968           "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
969           separator_char, separator_char, separator_char, (int)regex_sed.size(),
970           regex_sed.data());
971       return error;
972     } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
973       error.SetErrorStringWithFormat(
974           "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
975           separator_char, separator_char, separator_char, (int)regex_sed.size(),
976           regex_sed.data());
977       return error;
978     }
979 
980     if (!check_only) {
981       std::string regex(std::string(regex_sed.substr(
982           first_separator_char_pos + 1,
983           second_separator_char_pos - first_separator_char_pos - 1)));
984       std::string subst(std::string(regex_sed.substr(
985           second_separator_char_pos + 1,
986           third_separator_char_pos - second_separator_char_pos - 1)));
987       m_regex_cmd_up->AddRegexCommand(regex, subst);
988     }
989     return error;
990   }
991 
992   void AddRegexCommandToInterpreter() {
993     if (m_regex_cmd_up) {
994       if (m_regex_cmd_up->HasRegexEntries()) {
995         CommandObjectSP cmd_sp(m_regex_cmd_up.release());
996         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
997       }
998     }
999   }
1000 
1001 private:
1002   std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_up;
1003 
1004   class CommandOptions : public Options {
1005   public:
1006     CommandOptions() : Options() {}
1007 
1008     ~CommandOptions() override = default;
1009 
1010     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1011                           ExecutionContext *execution_context) override {
1012       Status error;
1013       const int short_option = m_getopt_table[option_idx].val;
1014 
1015       switch (short_option) {
1016       case 'h':
1017         m_help.assign(std::string(option_arg));
1018         break;
1019       case 's':
1020         m_syntax.assign(std::string(option_arg));
1021         break;
1022       default:
1023         llvm_unreachable("Unimplemented option");
1024       }
1025 
1026       return error;
1027     }
1028 
1029     void OptionParsingStarting(ExecutionContext *execution_context) override {
1030       m_help.clear();
1031       m_syntax.clear();
1032     }
1033 
1034     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1035       return llvm::makeArrayRef(g_regex_options);
1036     }
1037 
1038     llvm::StringRef GetHelp() { return m_help; }
1039 
1040     llvm::StringRef GetSyntax() { return m_syntax; }
1041 
1042   protected:
1043     // Instance variables to hold the values for command options.
1044 
1045     std::string m_help;
1046     std::string m_syntax;
1047   };
1048 
1049   Options *GetOptions() override { return &m_options; }
1050 
1051   CommandOptions m_options;
1052 };
1053 
1054 class CommandObjectPythonFunction : public CommandObjectRaw {
1055 public:
1056   CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
1057                               std::string funct, std::string help,
1058                               ScriptedCommandSynchronicity synch)
1059       : CommandObjectRaw(interpreter, name), m_function_name(funct),
1060         m_synchro(synch), m_fetched_help_long(false) {
1061     if (!help.empty())
1062       SetHelp(help);
1063     else {
1064       StreamString stream;
1065       stream.Printf("For more information run 'help %s'", name.c_str());
1066       SetHelp(stream.GetString());
1067     }
1068   }
1069 
1070   ~CommandObjectPythonFunction() override = default;
1071 
1072   bool IsRemovable() const override { return true; }
1073 
1074   const std::string &GetFunctionName() { return m_function_name; }
1075 
1076   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1077 
1078   llvm::StringRef GetHelpLong() override {
1079     if (m_fetched_help_long)
1080       return CommandObjectRaw::GetHelpLong();
1081 
1082     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1083     if (!scripter)
1084       return CommandObjectRaw::GetHelpLong();
1085 
1086     std::string docstring;
1087     m_fetched_help_long =
1088         scripter->GetDocumentationForItem(m_function_name.c_str(), docstring);
1089     if (!docstring.empty())
1090       SetHelpLong(docstring);
1091     return CommandObjectRaw::GetHelpLong();
1092   }
1093 
1094 protected:
1095   bool DoExecute(llvm::StringRef raw_command_line,
1096                  CommandReturnObject &result) override {
1097     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1098 
1099     Status error;
1100 
1101     result.SetStatus(eReturnStatusInvalid);
1102 
1103     if (!scripter || !scripter->RunScriptBasedCommand(
1104                          m_function_name.c_str(), raw_command_line, m_synchro,
1105                          result, error, m_exe_ctx)) {
1106       result.AppendError(error.AsCString());
1107       result.SetStatus(eReturnStatusFailed);
1108     } else {
1109       // Don't change the status if the command already set it...
1110       if (result.GetStatus() == eReturnStatusInvalid) {
1111         if (result.GetOutputData().empty())
1112           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1113         else
1114           result.SetStatus(eReturnStatusSuccessFinishResult);
1115       }
1116     }
1117 
1118     return result.Succeeded();
1119   }
1120 
1121 private:
1122   std::string m_function_name;
1123   ScriptedCommandSynchronicity m_synchro;
1124   bool m_fetched_help_long;
1125 };
1126 
1127 class CommandObjectScriptingObject : public CommandObjectRaw {
1128 public:
1129   CommandObjectScriptingObject(CommandInterpreter &interpreter,
1130                                std::string name,
1131                                StructuredData::GenericSP cmd_obj_sp,
1132                                ScriptedCommandSynchronicity synch)
1133       : CommandObjectRaw(interpreter, name), m_cmd_obj_sp(cmd_obj_sp),
1134         m_synchro(synch), m_fetched_help_short(false),
1135         m_fetched_help_long(false) {
1136     StreamString stream;
1137     stream.Printf("For more information run 'help %s'", name.c_str());
1138     SetHelp(stream.GetString());
1139     if (ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter())
1140       GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
1141   }
1142 
1143   ~CommandObjectScriptingObject() override = default;
1144 
1145   bool IsRemovable() const override { return true; }
1146 
1147   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1148 
1149   llvm::StringRef GetHelp() override {
1150     if (m_fetched_help_short)
1151       return CommandObjectRaw::GetHelp();
1152     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1153     if (!scripter)
1154       return CommandObjectRaw::GetHelp();
1155     std::string docstring;
1156     m_fetched_help_short =
1157         scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
1158     if (!docstring.empty())
1159       SetHelp(docstring);
1160 
1161     return CommandObjectRaw::GetHelp();
1162   }
1163 
1164   llvm::StringRef GetHelpLong() override {
1165     if (m_fetched_help_long)
1166       return CommandObjectRaw::GetHelpLong();
1167 
1168     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1169     if (!scripter)
1170       return CommandObjectRaw::GetHelpLong();
1171 
1172     std::string docstring;
1173     m_fetched_help_long =
1174         scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
1175     if (!docstring.empty())
1176       SetHelpLong(docstring);
1177     return CommandObjectRaw::GetHelpLong();
1178   }
1179 
1180 protected:
1181   bool DoExecute(llvm::StringRef raw_command_line,
1182                  CommandReturnObject &result) override {
1183     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1184 
1185     Status error;
1186 
1187     result.SetStatus(eReturnStatusInvalid);
1188 
1189     if (!scripter ||
1190         !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1191                                          m_synchro, result, error, m_exe_ctx)) {
1192       result.AppendError(error.AsCString());
1193       result.SetStatus(eReturnStatusFailed);
1194     } else {
1195       // Don't change the status if the command already set it...
1196       if (result.GetStatus() == eReturnStatusInvalid) {
1197         if (result.GetOutputData().empty())
1198           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1199         else
1200           result.SetStatus(eReturnStatusSuccessFinishResult);
1201       }
1202     }
1203 
1204     return result.Succeeded();
1205   }
1206 
1207 private:
1208   StructuredData::GenericSP m_cmd_obj_sp;
1209   ScriptedCommandSynchronicity m_synchro;
1210   bool m_fetched_help_short : 1;
1211   bool m_fetched_help_long : 1;
1212 };
1213 
1214 // CommandObjectCommandsScriptImport
1215 #define LLDB_OPTIONS_script_import
1216 #include "CommandOptions.inc"
1217 
1218 class CommandObjectCommandsScriptImport : public CommandObjectParsed {
1219 public:
1220   CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1221       : CommandObjectParsed(interpreter, "command script import",
1222                             "Import a scripting module in LLDB.", nullptr),
1223         m_options() {
1224     CommandArgumentEntry arg1;
1225     CommandArgumentData cmd_arg;
1226 
1227     // Define the first (and only) variant of this arg.
1228     cmd_arg.arg_type = eArgTypeFilename;
1229     cmd_arg.arg_repetition = eArgRepeatPlus;
1230 
1231     // There is only one variant this argument could be; put it into the
1232     // argument entry.
1233     arg1.push_back(cmd_arg);
1234 
1235     // Push the data for the first argument into the m_arguments vector.
1236     m_arguments.push_back(arg1);
1237   }
1238 
1239   ~CommandObjectCommandsScriptImport() override = default;
1240 
1241   void
1242   HandleArgumentCompletion(CompletionRequest &request,
1243                            OptionElementVector &opt_element_vector) override {
1244     CommandCompletions::InvokeCommonCompletionCallbacks(
1245         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
1246         request, nullptr);
1247   }
1248 
1249   Options *GetOptions() override { return &m_options; }
1250 
1251 protected:
1252   class CommandOptions : public Options {
1253   public:
1254     CommandOptions() : Options() {}
1255 
1256     ~CommandOptions() override = default;
1257 
1258     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1259                           ExecutionContext *execution_context) override {
1260       Status error;
1261       const int short_option = m_getopt_table[option_idx].val;
1262 
1263       switch (short_option) {
1264       case 'r':
1265         // NO-OP
1266         break;
1267       case 'c':
1268         relative_to_command_file = true;
1269         break;
1270       default:
1271         llvm_unreachable("Unimplemented option");
1272       }
1273 
1274       return error;
1275     }
1276 
1277     void OptionParsingStarting(ExecutionContext *execution_context) override {
1278       relative_to_command_file = false;
1279     }
1280 
1281     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1282       return llvm::makeArrayRef(g_script_import_options);
1283     }
1284     bool relative_to_command_file = false;
1285   };
1286 
1287   bool DoExecute(Args &command, CommandReturnObject &result) override {
1288     if (command.empty()) {
1289       result.AppendError("command script import needs one or more arguments");
1290       result.SetStatus(eReturnStatusFailed);
1291       return false;
1292     }
1293 
1294     FileSpec source_dir = {};
1295     if (m_options.relative_to_command_file) {
1296       source_dir = GetDebugger().GetCommandInterpreter().GetCurrentSourceDir();
1297       if (!source_dir) {
1298         result.AppendError("command script import -c can only be specified "
1299                            "from a command file");
1300         result.SetStatus(eReturnStatusFailed);
1301         return false;
1302       }
1303     }
1304 
1305     for (auto &entry : command.entries()) {
1306       Status error;
1307 
1308       const bool init_session = true;
1309       // FIXME: this is necessary because CommandObject::CheckRequirements()
1310       // assumes that commands won't ever be recursively invoked, but it's
1311       // actually possible to craft a Python script that does other "command
1312       // script imports" in __lldb_init_module the real fix is to have
1313       // recursive commands possible with a CommandInvocation object separate
1314       // from the CommandObject itself, so that recursive command invocations
1315       // won't stomp on each other (wrt to execution contents, options, and
1316       // more)
1317       m_exe_ctx.Clear();
1318       if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule(
1319               entry.c_str(), init_session, error, nullptr, source_dir)) {
1320         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1321       } else {
1322         result.AppendErrorWithFormat("module importing failed: %s",
1323                                      error.AsCString());
1324         result.SetStatus(eReturnStatusFailed);
1325       }
1326     }
1327 
1328     return result.Succeeded();
1329   }
1330 
1331   CommandOptions m_options;
1332 };
1333 
1334 // CommandObjectCommandsScriptAdd
1335 static constexpr OptionEnumValueElement g_script_synchro_type[] = {
1336     {
1337         eScriptedCommandSynchronicitySynchronous,
1338         "synchronous",
1339         "Run synchronous",
1340     },
1341     {
1342         eScriptedCommandSynchronicityAsynchronous,
1343         "asynchronous",
1344         "Run asynchronous",
1345     },
1346     {
1347         eScriptedCommandSynchronicityCurrentValue,
1348         "current",
1349         "Do not alter current setting",
1350     },
1351 };
1352 
1353 static constexpr OptionEnumValues ScriptSynchroType() {
1354   return OptionEnumValues(g_script_synchro_type);
1355 }
1356 
1357 #define LLDB_OPTIONS_script_add
1358 #include "CommandOptions.inc"
1359 
1360 class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1361                                        public IOHandlerDelegateMultiline {
1362 public:
1363   CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1364       : CommandObjectParsed(interpreter, "command script add",
1365                             "Add a scripted function as an LLDB command.",
1366                             nullptr),
1367         IOHandlerDelegateMultiline("DONE"), m_options() {
1368     CommandArgumentEntry arg1;
1369     CommandArgumentData cmd_arg;
1370 
1371     // Define the first (and only) variant of this arg.
1372     cmd_arg.arg_type = eArgTypeCommandName;
1373     cmd_arg.arg_repetition = eArgRepeatPlain;
1374 
1375     // There is only one variant this argument could be; put it into the
1376     // argument entry.
1377     arg1.push_back(cmd_arg);
1378 
1379     // Push the data for the first argument into the m_arguments vector.
1380     m_arguments.push_back(arg1);
1381   }
1382 
1383   ~CommandObjectCommandsScriptAdd() override = default;
1384 
1385   Options *GetOptions() override { return &m_options; }
1386 
1387 protected:
1388   class CommandOptions : public Options {
1389   public:
1390     CommandOptions()
1391         : Options(), m_class_name(), m_funct_name(), m_short_help(),
1392           m_synchronicity(eScriptedCommandSynchronicitySynchronous) {}
1393 
1394     ~CommandOptions() override = default;
1395 
1396     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1397                           ExecutionContext *execution_context) override {
1398       Status error;
1399       const int short_option = m_getopt_table[option_idx].val;
1400 
1401       switch (short_option) {
1402       case 'f':
1403         if (!option_arg.empty())
1404           m_funct_name = std::string(option_arg);
1405         break;
1406       case 'c':
1407         if (!option_arg.empty())
1408           m_class_name = std::string(option_arg);
1409         break;
1410       case 'h':
1411         if (!option_arg.empty())
1412           m_short_help = std::string(option_arg);
1413         break;
1414       case 's':
1415         m_synchronicity =
1416             (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum(
1417                 option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
1418         if (!error.Success())
1419           error.SetErrorStringWithFormat(
1420               "unrecognized value for synchronicity '%s'",
1421               option_arg.str().c_str());
1422         break;
1423       default:
1424         llvm_unreachable("Unimplemented option");
1425       }
1426 
1427       return error;
1428     }
1429 
1430     void OptionParsingStarting(ExecutionContext *execution_context) override {
1431       m_class_name.clear();
1432       m_funct_name.clear();
1433       m_short_help.clear();
1434       m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1435     }
1436 
1437     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1438       return llvm::makeArrayRef(g_script_add_options);
1439     }
1440 
1441     // Instance variables to hold the values for command options.
1442 
1443     std::string m_class_name;
1444     std::string m_funct_name;
1445     std::string m_short_help;
1446     ScriptedCommandSynchronicity m_synchronicity;
1447   };
1448 
1449   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
1450     StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
1451     if (output_sp && interactive) {
1452       output_sp->PutCString(g_python_command_instructions);
1453       output_sp->Flush();
1454     }
1455   }
1456 
1457   void IOHandlerInputComplete(IOHandler &io_handler,
1458                               std::string &data) override {
1459     StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
1460 
1461     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1462     if (interpreter) {
1463 
1464       StringList lines;
1465       lines.SplitIntoLines(data);
1466       if (lines.GetSize() > 0) {
1467         std::string funct_name_str;
1468         if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1469           if (funct_name_str.empty()) {
1470             error_sp->Printf("error: unable to obtain a function name, didn't "
1471                              "add python command.\n");
1472             error_sp->Flush();
1473           } else {
1474             // everything should be fine now, let's add this alias
1475 
1476             CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
1477                 m_interpreter, m_cmd_name, funct_name_str, m_short_help,
1478                 m_synchronicity));
1479 
1480             if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp,
1481                                               true)) {
1482               error_sp->Printf("error: unable to add selected command, didn't "
1483                                "add python command.\n");
1484               error_sp->Flush();
1485             }
1486           }
1487         } else {
1488           error_sp->Printf(
1489               "error: unable to create function, didn't add python command.\n");
1490           error_sp->Flush();
1491         }
1492       } else {
1493         error_sp->Printf("error: empty function, didn't add python command.\n");
1494         error_sp->Flush();
1495       }
1496     } else {
1497       error_sp->Printf(
1498           "error: script interpreter missing, didn't add python command.\n");
1499       error_sp->Flush();
1500     }
1501 
1502     io_handler.SetIsDone(true);
1503   }
1504 
1505   bool DoExecute(Args &command, CommandReturnObject &result) override {
1506     if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) {
1507       result.AppendError("only scripting language supported for scripted "
1508                          "commands is currently Python");
1509       result.SetStatus(eReturnStatusFailed);
1510       return false;
1511     }
1512 
1513     if (command.GetArgumentCount() != 1) {
1514       result.AppendError("'command script add' requires one argument");
1515       result.SetStatus(eReturnStatusFailed);
1516       return false;
1517     }
1518 
1519     // Store the options in case we get multi-line input
1520     m_cmd_name = std::string(command[0].ref());
1521     m_short_help.assign(m_options.m_short_help);
1522     m_synchronicity = m_options.m_synchronicity;
1523 
1524     if (m_options.m_class_name.empty()) {
1525       if (m_options.m_funct_name.empty()) {
1526         m_interpreter.GetPythonCommandsFromIOHandler(
1527             "     ", // Prompt
1528             *this);  // IOHandlerDelegate
1529       } else {
1530         CommandObjectSP new_cmd(new CommandObjectPythonFunction(
1531             m_interpreter, m_cmd_name, m_options.m_funct_name,
1532             m_options.m_short_help, m_synchronicity));
1533         if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1534           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1535         } else {
1536           result.AppendError("cannot add command");
1537           result.SetStatus(eReturnStatusFailed);
1538         }
1539       }
1540     } else {
1541       ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1542       if (!interpreter) {
1543         result.AppendError("cannot find ScriptInterpreter");
1544         result.SetStatus(eReturnStatusFailed);
1545         return false;
1546       }
1547 
1548       auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1549           m_options.m_class_name.c_str());
1550       if (!cmd_obj_sp) {
1551         result.AppendError("cannot create helper object");
1552         result.SetStatus(eReturnStatusFailed);
1553         return false;
1554       }
1555 
1556       CommandObjectSP new_cmd(new CommandObjectScriptingObject(
1557           m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1558       if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1559         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1560       } else {
1561         result.AppendError("cannot add command");
1562         result.SetStatus(eReturnStatusFailed);
1563       }
1564     }
1565 
1566     return result.Succeeded();
1567   }
1568 
1569   CommandOptions m_options;
1570   std::string m_cmd_name;
1571   std::string m_short_help;
1572   ScriptedCommandSynchronicity m_synchronicity;
1573 };
1574 
1575 // CommandObjectCommandsScriptList
1576 
1577 class CommandObjectCommandsScriptList : public CommandObjectParsed {
1578 public:
1579   CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1580       : CommandObjectParsed(interpreter, "command script list",
1581                             "List defined scripted commands.", nullptr) {}
1582 
1583   ~CommandObjectCommandsScriptList() override = default;
1584 
1585   bool DoExecute(Args &command, CommandReturnObject &result) override {
1586     if (command.GetArgumentCount() != 0) {
1587       result.AppendError("'command script list' doesn't take any arguments");
1588       result.SetStatus(eReturnStatusFailed);
1589       return false;
1590     }
1591 
1592     m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1593 
1594     result.SetStatus(eReturnStatusSuccessFinishResult);
1595 
1596     return true;
1597   }
1598 };
1599 
1600 // CommandObjectCommandsScriptClear
1601 
1602 class CommandObjectCommandsScriptClear : public CommandObjectParsed {
1603 public:
1604   CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1605       : CommandObjectParsed(interpreter, "command script clear",
1606                             "Delete all scripted commands.", nullptr) {}
1607 
1608   ~CommandObjectCommandsScriptClear() override = default;
1609 
1610 protected:
1611   bool DoExecute(Args &command, CommandReturnObject &result) override {
1612     if (command.GetArgumentCount() != 0) {
1613       result.AppendError("'command script clear' doesn't take any arguments");
1614       result.SetStatus(eReturnStatusFailed);
1615       return false;
1616     }
1617 
1618     m_interpreter.RemoveAllUser();
1619 
1620     result.SetStatus(eReturnStatusSuccessFinishResult);
1621 
1622     return true;
1623   }
1624 };
1625 
1626 // CommandObjectCommandsScriptDelete
1627 
1628 class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
1629 public:
1630   CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1631       : CommandObjectParsed(interpreter, "command script delete",
1632                             "Delete a scripted command.", nullptr) {
1633     CommandArgumentEntry arg1;
1634     CommandArgumentData cmd_arg;
1635 
1636     // Define the first (and only) variant of this arg.
1637     cmd_arg.arg_type = eArgTypeCommandName;
1638     cmd_arg.arg_repetition = eArgRepeatPlain;
1639 
1640     // There is only one variant this argument could be; put it into the
1641     // argument entry.
1642     arg1.push_back(cmd_arg);
1643 
1644     // Push the data for the first argument into the m_arguments vector.
1645     m_arguments.push_back(arg1);
1646   }
1647 
1648   ~CommandObjectCommandsScriptDelete() override = default;
1649 
1650   void
1651   HandleArgumentCompletion(CompletionRequest &request,
1652                            OptionElementVector &opt_element_vector) override {
1653     if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
1654       return;
1655 
1656     for (const auto &c : m_interpreter.GetUserCommands())
1657       request.TryCompleteCurrentArg(c.first, c.second->GetHelp());
1658   }
1659 
1660 protected:
1661   bool DoExecute(Args &command, CommandReturnObject &result) override {
1662 
1663     if (command.GetArgumentCount() != 1) {
1664       result.AppendError("'command script delete' requires one argument");
1665       result.SetStatus(eReturnStatusFailed);
1666       return false;
1667     }
1668 
1669     auto cmd_name = command[0].ref();
1670 
1671     if (cmd_name.empty() || !m_interpreter.HasUserCommands() ||
1672         !m_interpreter.UserCommandExists(cmd_name)) {
1673       result.AppendErrorWithFormat("command %s not found", command[0].c_str());
1674       result.SetStatus(eReturnStatusFailed);
1675       return false;
1676     }
1677 
1678     m_interpreter.RemoveUser(cmd_name);
1679     result.SetStatus(eReturnStatusSuccessFinishResult);
1680     return true;
1681   }
1682 };
1683 
1684 #pragma mark CommandObjectMultiwordCommandsScript
1685 
1686 // CommandObjectMultiwordCommandsScript
1687 
1688 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
1689 public:
1690   CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1691       : CommandObjectMultiword(
1692             interpreter, "command script",
1693             "Commands for managing custom "
1694             "commands implemented by "
1695             "interpreter scripts.",
1696             "command script <subcommand> [<subcommand-options>]") {
1697     LoadSubCommand("add", CommandObjectSP(
1698                               new CommandObjectCommandsScriptAdd(interpreter)));
1699     LoadSubCommand(
1700         "delete",
1701         CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1702     LoadSubCommand(
1703         "clear",
1704         CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1705     LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1706                                interpreter)));
1707     LoadSubCommand(
1708         "import",
1709         CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1710   }
1711 
1712   ~CommandObjectMultiwordCommandsScript() override = default;
1713 };
1714 
1715 #pragma mark CommandObjectMultiwordCommands
1716 
1717 // CommandObjectMultiwordCommands
1718 
1719 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
1720     CommandInterpreter &interpreter)
1721     : CommandObjectMultiword(interpreter, "command",
1722                              "Commands for managing custom LLDB commands.",
1723                              "command <subcommand> [<subcommand-options>]") {
1724   LoadSubCommand("source",
1725                  CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
1726   LoadSubCommand("alias",
1727                  CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
1728   LoadSubCommand("unalias", CommandObjectSP(
1729                                 new CommandObjectCommandsUnalias(interpreter)));
1730   LoadSubCommand("delete",
1731                  CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
1732   LoadSubCommand(
1733       "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
1734   LoadSubCommand(
1735       "script",
1736       CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
1737 }
1738 
1739 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
1740