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