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