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())) {
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());
562       if (use_subcommand)
563         tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName());
564 
565       args.GetCommandString(args_string);
566     }
567 
568     if (m_interpreter.AliasExists(alias_command) ||
569         m_interpreter.UserCommandExists(alias_command)) {
570       result.AppendWarningWithFormat(
571           "Overwriting existing definition for '%s'.\n", alias_command.c_str());
572     }
573 
574     if (CommandAlias *alias = m_interpreter.AddAlias(
575             alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp,
576             args_string)) {
577       if (m_command_options.m_help.OptionWasSet())
578         alias->SetHelp(m_command_options.m_help.GetCurrentValue());
579       if (m_command_options.m_long_help.OptionWasSet())
580         alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
581       result.SetStatus(eReturnStatusSuccessFinishNoResult);
582     } else {
583       result.AppendError("Unable to create requested alias.\n");
584       result.SetStatus(eReturnStatusFailed);
585       return false;
586     }
587 
588     return result.Succeeded();
589   }
590 };
591 
592 #pragma mark CommandObjectCommandsUnalias
593 // CommandObjectCommandsUnalias
594 
595 class CommandObjectCommandsUnalias : public CommandObjectParsed {
596 public:
597   CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
598       : CommandObjectParsed(
599             interpreter, "command unalias",
600             "Delete one or more custom commands defined by 'command alias'.",
601             nullptr) {
602     CommandArgumentEntry arg;
603     CommandArgumentData alias_arg;
604 
605     // Define the first (and only) variant of this arg.
606     alias_arg.arg_type = eArgTypeAliasName;
607     alias_arg.arg_repetition = eArgRepeatPlain;
608 
609     // There is only one variant this argument could be; put it into the
610     // argument entry.
611     arg.push_back(alias_arg);
612 
613     // Push the data for the first argument into the m_arguments vector.
614     m_arguments.push_back(arg);
615   }
616 
617   ~CommandObjectCommandsUnalias() override = default;
618 
619   void
620   HandleArgumentCompletion(CompletionRequest &request,
621                            OptionElementVector &opt_element_vector) override {
622     if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
623       return;
624 
625     for (const auto &ent : m_interpreter.GetAliases()) {
626       request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp());
627     }
628   }
629 
630 protected:
631   bool DoExecute(Args &args, CommandReturnObject &result) override {
632     CommandObject::CommandMap::iterator pos;
633     CommandObject *cmd_obj;
634 
635     if (args.empty()) {
636       result.AppendError("must call 'unalias' with a valid alias");
637       result.SetStatus(eReturnStatusFailed);
638       return false;
639     }
640 
641     auto command_name = args[0].ref();
642     cmd_obj = m_interpreter.GetCommandObject(command_name);
643     if (!cmd_obj) {
644       result.AppendErrorWithFormat(
645           "'%s' is not a known command.\nTry 'help' to see a "
646           "current list of commands.\n",
647           args[0].c_str());
648       result.SetStatus(eReturnStatusFailed);
649       return false;
650     }
651 
652     if (m_interpreter.CommandExists(command_name)) {
653       if (cmd_obj->IsRemovable()) {
654         result.AppendErrorWithFormat(
655             "'%s' is not an alias, it is a debugger command which can be "
656             "removed using the 'command delete' command.\n",
657             args[0].c_str());
658       } else {
659         result.AppendErrorWithFormat(
660             "'%s' is a permanent debugger command and cannot be removed.\n",
661             args[0].c_str());
662       }
663       result.SetStatus(eReturnStatusFailed);
664       return false;
665     }
666 
667     if (!m_interpreter.RemoveAlias(command_name)) {
668       if (m_interpreter.AliasExists(command_name))
669         result.AppendErrorWithFormat(
670             "Error occurred while attempting to unalias '%s'.\n",
671             args[0].c_str());
672       else
673         result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
674                                      args[0].c_str());
675       result.SetStatus(eReturnStatusFailed);
676       return false;
677     }
678 
679     result.SetStatus(eReturnStatusSuccessFinishNoResult);
680     return result.Succeeded();
681   }
682 };
683 
684 #pragma mark CommandObjectCommandsDelete
685 // CommandObjectCommandsDelete
686 
687 class CommandObjectCommandsDelete : public CommandObjectParsed {
688 public:
689   CommandObjectCommandsDelete(CommandInterpreter &interpreter)
690       : CommandObjectParsed(
691             interpreter, "command delete",
692             "Delete one or more custom commands defined by 'command regex'.",
693             nullptr) {
694     CommandArgumentEntry arg;
695     CommandArgumentData alias_arg;
696 
697     // Define the first (and only) variant of this arg.
698     alias_arg.arg_type = eArgTypeCommandName;
699     alias_arg.arg_repetition = eArgRepeatPlain;
700 
701     // There is only one variant this argument could be; put it into the
702     // argument entry.
703     arg.push_back(alias_arg);
704 
705     // Push the data for the first argument into the m_arguments vector.
706     m_arguments.push_back(arg);
707   }
708 
709   ~CommandObjectCommandsDelete() override = default;
710 
711   void
712   HandleArgumentCompletion(CompletionRequest &request,
713                            OptionElementVector &opt_element_vector) override {
714     if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
715       return;
716 
717     for (const auto &ent : m_interpreter.GetCommands()) {
718       if (ent.second->IsRemovable())
719         request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp());
720     }
721   }
722 
723 protected:
724   bool DoExecute(Args &args, CommandReturnObject &result) override {
725     CommandObject::CommandMap::iterator pos;
726 
727     if (args.empty()) {
728       result.AppendErrorWithFormat("must call '%s' with one or more valid user "
729                                    "defined regular expression command names",
730                                    GetCommandName().str().c_str());
731       result.SetStatus(eReturnStatusFailed);
732       return false;
733     }
734 
735     auto command_name = args[0].ref();
736     if (!m_interpreter.CommandExists(command_name)) {
737       StreamString error_msg_stream;
738       const bool generate_upropos = true;
739       const bool generate_type_lookup = false;
740       CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
741           &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(),
742           generate_upropos, generate_type_lookup);
743       result.AppendError(error_msg_stream.GetString());
744       result.SetStatus(eReturnStatusFailed);
745       return false;
746     }
747 
748     if (!m_interpreter.RemoveCommand(command_name)) {
749       result.AppendErrorWithFormat(
750           "'%s' is a permanent debugger command and cannot be removed.\n",
751           args[0].c_str());
752       result.SetStatus(eReturnStatusFailed);
753       return false;
754     }
755 
756     result.SetStatus(eReturnStatusSuccessFinishNoResult);
757     return true;
758   }
759 };
760 
761 // CommandObjectCommandsAddRegex
762 
763 #define LLDB_OPTIONS_regex
764 #include "CommandOptions.inc"
765 
766 #pragma mark CommandObjectCommandsAddRegex
767 
768 class CommandObjectCommandsAddRegex : public CommandObjectParsed,
769                                       public IOHandlerDelegateMultiline {
770 public:
771   CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
772       : CommandObjectParsed(
773             interpreter, "command regex",
774             "Define a custom command in terms of "
775             "existing commands by matching "
776             "regular expressions.",
777             "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
778         IOHandlerDelegateMultiline("",
779                                    IOHandlerDelegate::Completion::LLDBCommand),
780         m_options() {
781     SetHelpLong(
782         R"(
783 )"
784         "This command allows the user to create powerful regular expression commands \
785 with substitutions. The regular expressions and substitutions are specified \
786 using the regular expression substitution format of:"
787         R"(
788 
789     s/<regex>/<subst>/
790 
791 )"
792         "<regex> is a regular expression that can use parenthesis to capture regular \
793 expression input and substitute the captured matches in the output using %1 \
794 for the first match, %2 for the second, and so on."
795         R"(
796 
797 )"
798         "The regular expressions can all be specified on the command line if more than \
799 one argument is provided. If just the command name is provided on the command \
800 line, then the regular expressions and substitutions can be entered on separate \
801 lines, followed by an empty line to terminate the command definition."
802         R"(
803 
804 EXAMPLES
805 
806 )"
807         "The following example will define a regular expression command named 'f' that \
808 will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
809 a number follows 'f':"
810         R"(
811 
812     (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
813   }
814 
815   ~CommandObjectCommandsAddRegex() override = default;
816 
817 protected:
818   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
819     StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
820     if (output_sp && interactive) {
821       output_sp->PutCString("Enter one or more sed substitution commands in "
822                             "the form: 's/<regex>/<subst>/'.\nTerminate the "
823                             "substitution list with an empty line.\n");
824       output_sp->Flush();
825     }
826   }
827 
828   void IOHandlerInputComplete(IOHandler &io_handler,
829                               std::string &data) override {
830     io_handler.SetIsDone(true);
831     if (m_regex_cmd_up) {
832       StringList lines;
833       if (lines.SplitIntoLines(data)) {
834         bool check_only = false;
835         for (const std::string &line : lines) {
836           Status error = AppendRegexSubstitution(line, check_only);
837           if (error.Fail()) {
838             if (!GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) {
839               StreamSP out_stream = GetDebugger().GetAsyncOutputStream();
840               out_stream->Printf("error: %s\n", error.AsCString());
841             }
842           }
843         }
844       }
845       if (m_regex_cmd_up->HasRegexEntries()) {
846         CommandObjectSP cmd_sp(m_regex_cmd_up.release());
847         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
848       }
849     }
850   }
851 
852   bool DoExecute(Args &command, CommandReturnObject &result) override {
853     const size_t argc = command.GetArgumentCount();
854     if (argc == 0) {
855       result.AppendError("usage: 'command regex <command-name> "
856                          "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
857       result.SetStatus(eReturnStatusFailed);
858       return false;
859     }
860 
861     Status error;
862     auto name = command[0].ref();
863     m_regex_cmd_up = std::make_unique<CommandObjectRegexCommand>(
864         m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0,
865         true);
866 
867     if (argc == 1) {
868       Debugger &debugger = GetDebugger();
869       bool color_prompt = debugger.GetUseColor();
870       const bool multiple_lines = true; // Get multiple lines
871       IOHandlerSP io_handler_sp(new IOHandlerEditline(
872           debugger, IOHandler::Type::Other,
873           "lldb-regex",          // Name of input reader for history
874           llvm::StringRef("> "), // Prompt
875           llvm::StringRef(),     // Continuation prompt
876           multiple_lines, color_prompt,
877           0, // Don't show line numbers
878           *this, nullptr));
879 
880       if (io_handler_sp) {
881         debugger.RunIOHandlerAsync(io_handler_sp);
882         result.SetStatus(eReturnStatusSuccessFinishNoResult);
883       }
884     } else {
885       for (auto &entry : command.entries().drop_front()) {
886         bool check_only = false;
887         error = AppendRegexSubstitution(entry.ref(), check_only);
888         if (error.Fail())
889           break;
890       }
891 
892       if (error.Success()) {
893         AddRegexCommandToInterpreter();
894       }
895     }
896     if (error.Fail()) {
897       result.AppendError(error.AsCString());
898       result.SetStatus(eReturnStatusFailed);
899     }
900 
901     return result.Succeeded();
902   }
903 
904   Status AppendRegexSubstitution(const llvm::StringRef &regex_sed,
905                                  bool check_only) {
906     Status error;
907 
908     if (!m_regex_cmd_up) {
909       error.SetErrorStringWithFormat(
910           "invalid regular expression command object for: '%.*s'",
911           (int)regex_sed.size(), regex_sed.data());
912       return error;
913     }
914 
915     size_t regex_sed_size = regex_sed.size();
916 
917     if (regex_sed_size <= 1) {
918       error.SetErrorStringWithFormat(
919           "regular expression substitution string is too short: '%.*s'",
920           (int)regex_sed.size(), regex_sed.data());
921       return error;
922     }
923 
924     if (regex_sed[0] != 's') {
925       error.SetErrorStringWithFormat("regular expression substitution string "
926                                      "doesn't start with 's': '%.*s'",
927                                      (int)regex_sed.size(), regex_sed.data());
928       return error;
929     }
930     const size_t first_separator_char_pos = 1;
931     // use the char that follows 's' as the regex separator character so we can
932     // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
933     const char separator_char = regex_sed[first_separator_char_pos];
934     const size_t second_separator_char_pos =
935         regex_sed.find(separator_char, first_separator_char_pos + 1);
936 
937     if (second_separator_char_pos == std::string::npos) {
938       error.SetErrorStringWithFormat(
939           "missing second '%c' separator char after '%.*s' in '%.*s'",
940           separator_char,
941           (int)(regex_sed.size() - first_separator_char_pos - 1),
942           regex_sed.data() + (first_separator_char_pos + 1),
943           (int)regex_sed.size(), regex_sed.data());
944       return error;
945     }
946 
947     const size_t third_separator_char_pos =
948         regex_sed.find(separator_char, second_separator_char_pos + 1);
949 
950     if (third_separator_char_pos == std::string::npos) {
951       error.SetErrorStringWithFormat(
952           "missing third '%c' separator char after '%.*s' in '%.*s'",
953           separator_char,
954           (int)(regex_sed.size() - second_separator_char_pos - 1),
955           regex_sed.data() + (second_separator_char_pos + 1),
956           (int)regex_sed.size(), regex_sed.data());
957       return error;
958     }
959 
960     if (third_separator_char_pos != regex_sed_size - 1) {
961       // Make sure that everything that follows the last regex separator char
962       if (regex_sed.find_first_not_of("\t\n\v\f\r ",
963                                       third_separator_char_pos + 1) !=
964           std::string::npos) {
965         error.SetErrorStringWithFormat(
966             "extra data found after the '%.*s' regular expression substitution "
967             "string: '%.*s'",
968             (int)third_separator_char_pos + 1, regex_sed.data(),
969             (int)(regex_sed.size() - third_separator_char_pos - 1),
970             regex_sed.data() + (third_separator_char_pos + 1));
971         return error;
972       }
973     } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
974       error.SetErrorStringWithFormat(
975           "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
976           separator_char, separator_char, separator_char, (int)regex_sed.size(),
977           regex_sed.data());
978       return error;
979     } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
980       error.SetErrorStringWithFormat(
981           "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
982           separator_char, separator_char, separator_char, (int)regex_sed.size(),
983           regex_sed.data());
984       return error;
985     }
986 
987     if (!check_only) {
988       std::string regex(std::string(regex_sed.substr(
989           first_separator_char_pos + 1,
990           second_separator_char_pos - first_separator_char_pos - 1)));
991       std::string subst(std::string(regex_sed.substr(
992           second_separator_char_pos + 1,
993           third_separator_char_pos - second_separator_char_pos - 1)));
994       m_regex_cmd_up->AddRegexCommand(regex, subst);
995     }
996     return error;
997   }
998 
999   void AddRegexCommandToInterpreter() {
1000     if (m_regex_cmd_up) {
1001       if (m_regex_cmd_up->HasRegexEntries()) {
1002         CommandObjectSP cmd_sp(m_regex_cmd_up.release());
1003         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1004       }
1005     }
1006   }
1007 
1008 private:
1009   std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_up;
1010 
1011   class CommandOptions : public Options {
1012   public:
1013     CommandOptions() : Options() {}
1014 
1015     ~CommandOptions() override = default;
1016 
1017     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1018                           ExecutionContext *execution_context) override {
1019       Status error;
1020       const int short_option = m_getopt_table[option_idx].val;
1021 
1022       switch (short_option) {
1023       case 'h':
1024         m_help.assign(std::string(option_arg));
1025         break;
1026       case 's':
1027         m_syntax.assign(std::string(option_arg));
1028         break;
1029       default:
1030         llvm_unreachable("Unimplemented option");
1031       }
1032 
1033       return error;
1034     }
1035 
1036     void OptionParsingStarting(ExecutionContext *execution_context) override {
1037       m_help.clear();
1038       m_syntax.clear();
1039     }
1040 
1041     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1042       return llvm::makeArrayRef(g_regex_options);
1043     }
1044 
1045     llvm::StringRef GetHelp() { return m_help; }
1046 
1047     llvm::StringRef GetSyntax() { return m_syntax; }
1048 
1049   protected:
1050     // Instance variables to hold the values for command options.
1051 
1052     std::string m_help;
1053     std::string m_syntax;
1054   };
1055 
1056   Options *GetOptions() override { return &m_options; }
1057 
1058   CommandOptions m_options;
1059 };
1060 
1061 class CommandObjectPythonFunction : public CommandObjectRaw {
1062 public:
1063   CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
1064                               std::string funct, std::string help,
1065                               ScriptedCommandSynchronicity synch)
1066       : CommandObjectRaw(interpreter, name), m_function_name(funct),
1067         m_synchro(synch), m_fetched_help_long(false) {
1068     if (!help.empty())
1069       SetHelp(help);
1070     else {
1071       StreamString stream;
1072       stream.Printf("For more information run 'help %s'", name.c_str());
1073       SetHelp(stream.GetString());
1074     }
1075   }
1076 
1077   ~CommandObjectPythonFunction() override = default;
1078 
1079   bool IsRemovable() const override { return true; }
1080 
1081   const std::string &GetFunctionName() { return m_function_name; }
1082 
1083   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1084 
1085   llvm::StringRef GetHelpLong() override {
1086     if (m_fetched_help_long)
1087       return CommandObjectRaw::GetHelpLong();
1088 
1089     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1090     if (!scripter)
1091       return CommandObjectRaw::GetHelpLong();
1092 
1093     std::string docstring;
1094     m_fetched_help_long =
1095         scripter->GetDocumentationForItem(m_function_name.c_str(), docstring);
1096     if (!docstring.empty())
1097       SetHelpLong(docstring);
1098     return CommandObjectRaw::GetHelpLong();
1099   }
1100 
1101 protected:
1102   bool DoExecute(llvm::StringRef raw_command_line,
1103                  CommandReturnObject &result) override {
1104     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1105 
1106     Status error;
1107 
1108     result.SetStatus(eReturnStatusInvalid);
1109 
1110     if (!scripter || !scripter->RunScriptBasedCommand(
1111                          m_function_name.c_str(), raw_command_line, m_synchro,
1112                          result, error, m_exe_ctx)) {
1113       result.AppendError(error.AsCString());
1114       result.SetStatus(eReturnStatusFailed);
1115     } else {
1116       // Don't change the status if the command already set it...
1117       if (result.GetStatus() == eReturnStatusInvalid) {
1118         if (result.GetOutputData().empty())
1119           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1120         else
1121           result.SetStatus(eReturnStatusSuccessFinishResult);
1122       }
1123     }
1124 
1125     return result.Succeeded();
1126   }
1127 
1128 private:
1129   std::string m_function_name;
1130   ScriptedCommandSynchronicity m_synchro;
1131   bool m_fetched_help_long;
1132 };
1133 
1134 class CommandObjectScriptingObject : public CommandObjectRaw {
1135 public:
1136   CommandObjectScriptingObject(CommandInterpreter &interpreter,
1137                                std::string name,
1138                                StructuredData::GenericSP cmd_obj_sp,
1139                                ScriptedCommandSynchronicity synch)
1140       : CommandObjectRaw(interpreter, name), m_cmd_obj_sp(cmd_obj_sp),
1141         m_synchro(synch), m_fetched_help_short(false),
1142         m_fetched_help_long(false) {
1143     StreamString stream;
1144     stream.Printf("For more information run 'help %s'", name.c_str());
1145     SetHelp(stream.GetString());
1146     if (ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter())
1147       GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
1148   }
1149 
1150   ~CommandObjectScriptingObject() override = default;
1151 
1152   bool IsRemovable() const override { return true; }
1153 
1154   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1155 
1156   llvm::StringRef GetHelp() override {
1157     if (m_fetched_help_short)
1158       return CommandObjectRaw::GetHelp();
1159     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1160     if (!scripter)
1161       return CommandObjectRaw::GetHelp();
1162     std::string docstring;
1163     m_fetched_help_short =
1164         scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
1165     if (!docstring.empty())
1166       SetHelp(docstring);
1167 
1168     return CommandObjectRaw::GetHelp();
1169   }
1170 
1171   llvm::StringRef GetHelpLong() override {
1172     if (m_fetched_help_long)
1173       return CommandObjectRaw::GetHelpLong();
1174 
1175     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1176     if (!scripter)
1177       return CommandObjectRaw::GetHelpLong();
1178 
1179     std::string docstring;
1180     m_fetched_help_long =
1181         scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
1182     if (!docstring.empty())
1183       SetHelpLong(docstring);
1184     return CommandObjectRaw::GetHelpLong();
1185   }
1186 
1187 protected:
1188   bool DoExecute(llvm::StringRef raw_command_line,
1189                  CommandReturnObject &result) override {
1190     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1191 
1192     Status error;
1193 
1194     result.SetStatus(eReturnStatusInvalid);
1195 
1196     if (!scripter ||
1197         !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1198                                          m_synchro, result, error, m_exe_ctx)) {
1199       result.AppendError(error.AsCString());
1200       result.SetStatus(eReturnStatusFailed);
1201     } else {
1202       // Don't change the status if the command already set it...
1203       if (result.GetStatus() == eReturnStatusInvalid) {
1204         if (result.GetOutputData().empty())
1205           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1206         else
1207           result.SetStatus(eReturnStatusSuccessFinishResult);
1208       }
1209     }
1210 
1211     return result.Succeeded();
1212   }
1213 
1214 private:
1215   StructuredData::GenericSP m_cmd_obj_sp;
1216   ScriptedCommandSynchronicity m_synchro;
1217   bool m_fetched_help_short : 1;
1218   bool m_fetched_help_long : 1;
1219 };
1220 
1221 // CommandObjectCommandsScriptImport
1222 #define LLDB_OPTIONS_script_import
1223 #include "CommandOptions.inc"
1224 
1225 class CommandObjectCommandsScriptImport : public CommandObjectParsed {
1226 public:
1227   CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1228       : CommandObjectParsed(interpreter, "command script import",
1229                             "Import a scripting module in LLDB.", nullptr),
1230         m_options() {
1231     CommandArgumentEntry arg1;
1232     CommandArgumentData cmd_arg;
1233 
1234     // Define the first (and only) variant of this arg.
1235     cmd_arg.arg_type = eArgTypeFilename;
1236     cmd_arg.arg_repetition = eArgRepeatPlus;
1237 
1238     // There is only one variant this argument could be; put it into the
1239     // argument entry.
1240     arg1.push_back(cmd_arg);
1241 
1242     // Push the data for the first argument into the m_arguments vector.
1243     m_arguments.push_back(arg1);
1244   }
1245 
1246   ~CommandObjectCommandsScriptImport() override = default;
1247 
1248   void
1249   HandleArgumentCompletion(CompletionRequest &request,
1250                            OptionElementVector &opt_element_vector) override {
1251     CommandCompletions::InvokeCommonCompletionCallbacks(
1252         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
1253         request, nullptr);
1254   }
1255 
1256   Options *GetOptions() override { return &m_options; }
1257 
1258 protected:
1259   class CommandOptions : public Options {
1260   public:
1261     CommandOptions() : Options() {}
1262 
1263     ~CommandOptions() override = default;
1264 
1265     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1266                           ExecutionContext *execution_context) override {
1267       Status error;
1268       const int short_option = m_getopt_table[option_idx].val;
1269 
1270       switch (short_option) {
1271       case 'r':
1272         // NO-OP
1273         break;
1274       case 'c':
1275         relative_to_command_file = true;
1276         break;
1277       default:
1278         llvm_unreachable("Unimplemented option");
1279       }
1280 
1281       return error;
1282     }
1283 
1284     void OptionParsingStarting(ExecutionContext *execution_context) override {
1285       relative_to_command_file = false;
1286     }
1287 
1288     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1289       return llvm::makeArrayRef(g_script_import_options);
1290     }
1291     bool relative_to_command_file = false;
1292   };
1293 
1294   bool DoExecute(Args &command, CommandReturnObject &result) override {
1295     if (command.empty()) {
1296       result.AppendError("command script import needs one or more arguments");
1297       result.SetStatus(eReturnStatusFailed);
1298       return false;
1299     }
1300 
1301     FileSpec source_dir = {};
1302     if (m_options.relative_to_command_file) {
1303       source_dir = GetDebugger().GetCommandInterpreter().GetCurrentSourceDir();
1304       if (!source_dir) {
1305         result.AppendError("command script import -c can only be specified "
1306                            "from a command file");
1307         result.SetStatus(eReturnStatusFailed);
1308         return false;
1309       }
1310     }
1311 
1312     for (auto &entry : command.entries()) {
1313       Status error;
1314 
1315       const bool init_session = true;
1316       // FIXME: this is necessary because CommandObject::CheckRequirements()
1317       // assumes that commands won't ever be recursively invoked, but it's
1318       // actually possible to craft a Python script that does other "command
1319       // script imports" in __lldb_init_module the real fix is to have
1320       // recursive commands possible with a CommandInvocation object separate
1321       // from the CommandObject itself, so that recursive command invocations
1322       // won't stomp on each other (wrt to execution contents, options, and
1323       // more)
1324       m_exe_ctx.Clear();
1325       if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule(
1326               entry.c_str(), init_session, error, nullptr, source_dir)) {
1327         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1328       } else {
1329         result.AppendErrorWithFormat("module importing failed: %s",
1330                                      error.AsCString());
1331         result.SetStatus(eReturnStatusFailed);
1332       }
1333     }
1334 
1335     return result.Succeeded();
1336   }
1337 
1338   CommandOptions m_options;
1339 };
1340 
1341 // CommandObjectCommandsScriptAdd
1342 static constexpr OptionEnumValueElement g_script_synchro_type[] = {
1343     {
1344         eScriptedCommandSynchronicitySynchronous,
1345         "synchronous",
1346         "Run synchronous",
1347     },
1348     {
1349         eScriptedCommandSynchronicityAsynchronous,
1350         "asynchronous",
1351         "Run asynchronous",
1352     },
1353     {
1354         eScriptedCommandSynchronicityCurrentValue,
1355         "current",
1356         "Do not alter current setting",
1357     },
1358 };
1359 
1360 static constexpr OptionEnumValues ScriptSynchroType() {
1361   return OptionEnumValues(g_script_synchro_type);
1362 }
1363 
1364 #define LLDB_OPTIONS_script_add
1365 #include "CommandOptions.inc"
1366 
1367 class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1368                                        public IOHandlerDelegateMultiline {
1369 public:
1370   CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1371       : CommandObjectParsed(interpreter, "command script add",
1372                             "Add a scripted function as an LLDB command.",
1373                             nullptr),
1374         IOHandlerDelegateMultiline("DONE"), m_options() {
1375     CommandArgumentEntry arg1;
1376     CommandArgumentData cmd_arg;
1377 
1378     // Define the first (and only) variant of this arg.
1379     cmd_arg.arg_type = eArgTypeCommandName;
1380     cmd_arg.arg_repetition = eArgRepeatPlain;
1381 
1382     // There is only one variant this argument could be; put it into the
1383     // argument entry.
1384     arg1.push_back(cmd_arg);
1385 
1386     // Push the data for the first argument into the m_arguments vector.
1387     m_arguments.push_back(arg1);
1388   }
1389 
1390   ~CommandObjectCommandsScriptAdd() override = default;
1391 
1392   Options *GetOptions() override { return &m_options; }
1393 
1394 protected:
1395   class CommandOptions : public Options {
1396   public:
1397     CommandOptions()
1398         : Options(), m_class_name(), m_funct_name(), m_short_help(),
1399           m_synchronicity(eScriptedCommandSynchronicitySynchronous) {}
1400 
1401     ~CommandOptions() override = default;
1402 
1403     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1404                           ExecutionContext *execution_context) override {
1405       Status error;
1406       const int short_option = m_getopt_table[option_idx].val;
1407 
1408       switch (short_option) {
1409       case 'f':
1410         if (!option_arg.empty())
1411           m_funct_name = std::string(option_arg);
1412         break;
1413       case 'c':
1414         if (!option_arg.empty())
1415           m_class_name = std::string(option_arg);
1416         break;
1417       case 'h':
1418         if (!option_arg.empty())
1419           m_short_help = std::string(option_arg);
1420         break;
1421       case 's':
1422         m_synchronicity =
1423             (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum(
1424                 option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
1425         if (!error.Success())
1426           error.SetErrorStringWithFormat(
1427               "unrecognized value for synchronicity '%s'",
1428               option_arg.str().c_str());
1429         break;
1430       default:
1431         llvm_unreachable("Unimplemented option");
1432       }
1433 
1434       return error;
1435     }
1436 
1437     void OptionParsingStarting(ExecutionContext *execution_context) override {
1438       m_class_name.clear();
1439       m_funct_name.clear();
1440       m_short_help.clear();
1441       m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1442     }
1443 
1444     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1445       return llvm::makeArrayRef(g_script_add_options);
1446     }
1447 
1448     // Instance variables to hold the values for command options.
1449 
1450     std::string m_class_name;
1451     std::string m_funct_name;
1452     std::string m_short_help;
1453     ScriptedCommandSynchronicity m_synchronicity;
1454   };
1455 
1456   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
1457     StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
1458     if (output_sp && interactive) {
1459       output_sp->PutCString(g_python_command_instructions);
1460       output_sp->Flush();
1461     }
1462   }
1463 
1464   void IOHandlerInputComplete(IOHandler &io_handler,
1465                               std::string &data) override {
1466     StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
1467 
1468     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1469     if (interpreter) {
1470 
1471       StringList lines;
1472       lines.SplitIntoLines(data);
1473       if (lines.GetSize() > 0) {
1474         std::string funct_name_str;
1475         if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1476           if (funct_name_str.empty()) {
1477             error_sp->Printf("error: unable to obtain a function name, didn't "
1478                              "add python command.\n");
1479             error_sp->Flush();
1480           } else {
1481             // everything should be fine now, let's add this alias
1482 
1483             CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
1484                 m_interpreter, m_cmd_name, funct_name_str, m_short_help,
1485                 m_synchronicity));
1486 
1487             if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp,
1488                                               true)) {
1489               error_sp->Printf("error: unable to add selected command, didn't "
1490                                "add python command.\n");
1491               error_sp->Flush();
1492             }
1493           }
1494         } else {
1495           error_sp->Printf(
1496               "error: unable to create function, didn't add python command.\n");
1497           error_sp->Flush();
1498         }
1499       } else {
1500         error_sp->Printf("error: empty function, didn't add python command.\n");
1501         error_sp->Flush();
1502       }
1503     } else {
1504       error_sp->Printf(
1505           "error: script interpreter missing, didn't add python command.\n");
1506       error_sp->Flush();
1507     }
1508 
1509     io_handler.SetIsDone(true);
1510   }
1511 
1512   bool DoExecute(Args &command, CommandReturnObject &result) override {
1513     if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) {
1514       result.AppendError("only scripting language supported for scripted "
1515                          "commands is currently Python");
1516       result.SetStatus(eReturnStatusFailed);
1517       return false;
1518     }
1519 
1520     if (command.GetArgumentCount() != 1) {
1521       result.AppendError("'command script add' requires one argument");
1522       result.SetStatus(eReturnStatusFailed);
1523       return false;
1524     }
1525 
1526     // Store the options in case we get multi-line input
1527     m_cmd_name = std::string(command[0].ref());
1528     m_short_help.assign(m_options.m_short_help);
1529     m_synchronicity = m_options.m_synchronicity;
1530 
1531     if (m_options.m_class_name.empty()) {
1532       if (m_options.m_funct_name.empty()) {
1533         m_interpreter.GetPythonCommandsFromIOHandler(
1534             "     ", // Prompt
1535             *this);  // IOHandlerDelegate
1536       } else {
1537         CommandObjectSP new_cmd(new CommandObjectPythonFunction(
1538             m_interpreter, m_cmd_name, m_options.m_funct_name,
1539             m_options.m_short_help, m_synchronicity));
1540         if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1541           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1542         } else {
1543           result.AppendError("cannot add command");
1544           result.SetStatus(eReturnStatusFailed);
1545         }
1546       }
1547     } else {
1548       ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1549       if (!interpreter) {
1550         result.AppendError("cannot find ScriptInterpreter");
1551         result.SetStatus(eReturnStatusFailed);
1552         return false;
1553       }
1554 
1555       auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1556           m_options.m_class_name.c_str());
1557       if (!cmd_obj_sp) {
1558         result.AppendError("cannot create helper object");
1559         result.SetStatus(eReturnStatusFailed);
1560         return false;
1561       }
1562 
1563       CommandObjectSP new_cmd(new CommandObjectScriptingObject(
1564           m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1565       if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1566         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1567       } else {
1568         result.AppendError("cannot add command");
1569         result.SetStatus(eReturnStatusFailed);
1570       }
1571     }
1572 
1573     return result.Succeeded();
1574   }
1575 
1576   CommandOptions m_options;
1577   std::string m_cmd_name;
1578   std::string m_short_help;
1579   ScriptedCommandSynchronicity m_synchronicity;
1580 };
1581 
1582 // CommandObjectCommandsScriptList
1583 
1584 class CommandObjectCommandsScriptList : public CommandObjectParsed {
1585 public:
1586   CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1587       : CommandObjectParsed(interpreter, "command script list",
1588                             "List defined scripted commands.", nullptr) {}
1589 
1590   ~CommandObjectCommandsScriptList() override = default;
1591 
1592   bool DoExecute(Args &command, CommandReturnObject &result) override {
1593     if (command.GetArgumentCount() != 0) {
1594       result.AppendError("'command script list' doesn't take any arguments");
1595       result.SetStatus(eReturnStatusFailed);
1596       return false;
1597     }
1598 
1599     m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1600 
1601     result.SetStatus(eReturnStatusSuccessFinishResult);
1602 
1603     return true;
1604   }
1605 };
1606 
1607 // CommandObjectCommandsScriptClear
1608 
1609 class CommandObjectCommandsScriptClear : public CommandObjectParsed {
1610 public:
1611   CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1612       : CommandObjectParsed(interpreter, "command script clear",
1613                             "Delete all scripted commands.", nullptr) {}
1614 
1615   ~CommandObjectCommandsScriptClear() override = default;
1616 
1617 protected:
1618   bool DoExecute(Args &command, CommandReturnObject &result) override {
1619     if (command.GetArgumentCount() != 0) {
1620       result.AppendError("'command script clear' doesn't take any arguments");
1621       result.SetStatus(eReturnStatusFailed);
1622       return false;
1623     }
1624 
1625     m_interpreter.RemoveAllUser();
1626 
1627     result.SetStatus(eReturnStatusSuccessFinishResult);
1628 
1629     return true;
1630   }
1631 };
1632 
1633 // CommandObjectCommandsScriptDelete
1634 
1635 class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
1636 public:
1637   CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1638       : CommandObjectParsed(interpreter, "command script delete",
1639                             "Delete a scripted command.", nullptr) {
1640     CommandArgumentEntry arg1;
1641     CommandArgumentData cmd_arg;
1642 
1643     // Define the first (and only) variant of this arg.
1644     cmd_arg.arg_type = eArgTypeCommandName;
1645     cmd_arg.arg_repetition = eArgRepeatPlain;
1646 
1647     // There is only one variant this argument could be; put it into the
1648     // argument entry.
1649     arg1.push_back(cmd_arg);
1650 
1651     // Push the data for the first argument into the m_arguments vector.
1652     m_arguments.push_back(arg1);
1653   }
1654 
1655   ~CommandObjectCommandsScriptDelete() override = default;
1656 
1657   void
1658   HandleArgumentCompletion(CompletionRequest &request,
1659                            OptionElementVector &opt_element_vector) override {
1660     if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
1661       return;
1662 
1663     for (const auto &c : m_interpreter.GetUserCommands())
1664       request.TryCompleteCurrentArg(c.first, c.second->GetHelp());
1665   }
1666 
1667 protected:
1668   bool DoExecute(Args &command, CommandReturnObject &result) override {
1669 
1670     if (command.GetArgumentCount() != 1) {
1671       result.AppendError("'command script delete' requires one argument");
1672       result.SetStatus(eReturnStatusFailed);
1673       return false;
1674     }
1675 
1676     auto cmd_name = command[0].ref();
1677 
1678     if (cmd_name.empty() || !m_interpreter.HasUserCommands() ||
1679         !m_interpreter.UserCommandExists(cmd_name)) {
1680       result.AppendErrorWithFormat("command %s not found", command[0].c_str());
1681       result.SetStatus(eReturnStatusFailed);
1682       return false;
1683     }
1684 
1685     m_interpreter.RemoveUser(cmd_name);
1686     result.SetStatus(eReturnStatusSuccessFinishResult);
1687     return true;
1688   }
1689 };
1690 
1691 #pragma mark CommandObjectMultiwordCommandsScript
1692 
1693 // CommandObjectMultiwordCommandsScript
1694 
1695 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
1696 public:
1697   CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1698       : CommandObjectMultiword(
1699             interpreter, "command script",
1700             "Commands for managing custom "
1701             "commands implemented by "
1702             "interpreter scripts.",
1703             "command script <subcommand> [<subcommand-options>]") {
1704     LoadSubCommand("add", CommandObjectSP(
1705                               new CommandObjectCommandsScriptAdd(interpreter)));
1706     LoadSubCommand(
1707         "delete",
1708         CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1709     LoadSubCommand(
1710         "clear",
1711         CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1712     LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1713                                interpreter)));
1714     LoadSubCommand(
1715         "import",
1716         CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1717   }
1718 
1719   ~CommandObjectMultiwordCommandsScript() override = default;
1720 };
1721 
1722 #pragma mark CommandObjectMultiwordCommands
1723 
1724 // CommandObjectMultiwordCommands
1725 
1726 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
1727     CommandInterpreter &interpreter)
1728     : CommandObjectMultiword(interpreter, "command",
1729                              "Commands for managing custom LLDB commands.",
1730                              "command <subcommand> [<subcommand-options>]") {
1731   LoadSubCommand("source",
1732                  CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
1733   LoadSubCommand("alias",
1734                  CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
1735   LoadSubCommand("unalias", CommandObjectSP(
1736                                 new CommandObjectCommandsUnalias(interpreter)));
1737   LoadSubCommand("delete",
1738                  CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
1739   LoadSubCommand(
1740       "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
1741   LoadSubCommand(
1742       "script",
1743       CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
1744 }
1745 
1746 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
1747