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