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