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