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