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 (command.empty()) {
1430       result.AppendError("command script import needs one or more arguments");
1431       result.SetStatus(eReturnStatusFailed);
1432       return false;
1433     }
1434 
1435     for (auto &entry : command.entries()) {
1436       Status error;
1437 
1438       const bool init_session = true;
1439       // FIXME: this is necessary because CommandObject::CheckRequirements()
1440       // assumes that commands won't ever be recursively invoked, but it's
1441       // actually possible to craft a Python script that does other "command
1442       // script imports" in __lldb_init_module the real fix is to have
1443       // recursive commands possible with a CommandInvocation object separate
1444       // from the CommandObject itself, so that recursive command invocations
1445       // won't stomp on each other (wrt to execution contents, options, and
1446       // more)
1447       m_exe_ctx.Clear();
1448       if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule(
1449               entry.c_str(), m_options.m_allow_reload, init_session, error)) {
1450         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1451       } else {
1452         result.AppendErrorWithFormat("module importing failed: %s",
1453                                      error.AsCString());
1454         result.SetStatus(eReturnStatusFailed);
1455       }
1456     }
1457 
1458     return result.Succeeded();
1459   }
1460 
1461   CommandOptions m_options;
1462 };
1463 
1464 // CommandObjectCommandsScriptAdd
1465 static constexpr OptionEnumValueElement g_script_synchro_type[] = {
1466     {
1467         eScriptedCommandSynchronicitySynchronous,
1468         "synchronous",
1469         "Run synchronous",
1470     },
1471     {
1472         eScriptedCommandSynchronicityAsynchronous,
1473         "asynchronous",
1474         "Run asynchronous",
1475     },
1476     {
1477         eScriptedCommandSynchronicityCurrentValue,
1478         "current",
1479         "Do not alter current setting",
1480     },
1481 };
1482 
1483 static constexpr OptionEnumValues ScriptSynchroType() {
1484   return OptionEnumValues(g_script_synchro_type);
1485 }
1486 
1487 #define LLDB_OPTIONS_script_add
1488 #include "CommandOptions.inc"
1489 
1490 class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1491                                        public IOHandlerDelegateMultiline {
1492 public:
1493   CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1494       : CommandObjectParsed(interpreter, "command script add",
1495                             "Add a scripted function as an LLDB command.",
1496                             nullptr),
1497         IOHandlerDelegateMultiline("DONE"), m_options() {
1498     CommandArgumentEntry arg1;
1499     CommandArgumentData cmd_arg;
1500 
1501     // Define the first (and only) variant of this arg.
1502     cmd_arg.arg_type = eArgTypeCommandName;
1503     cmd_arg.arg_repetition = eArgRepeatPlain;
1504 
1505     // There is only one variant this argument could be; put it into the
1506     // argument entry.
1507     arg1.push_back(cmd_arg);
1508 
1509     // Push the data for the first argument into the m_arguments vector.
1510     m_arguments.push_back(arg1);
1511   }
1512 
1513   ~CommandObjectCommandsScriptAdd() override = default;
1514 
1515   Options *GetOptions() override { return &m_options; }
1516 
1517 protected:
1518   class CommandOptions : public Options {
1519   public:
1520     CommandOptions()
1521         : Options(), m_class_name(), m_funct_name(), m_short_help(),
1522           m_synchronicity(eScriptedCommandSynchronicitySynchronous) {}
1523 
1524     ~CommandOptions() override = default;
1525 
1526     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1527                           ExecutionContext *execution_context) override {
1528       Status error;
1529       const int short_option = m_getopt_table[option_idx].val;
1530 
1531       switch (short_option) {
1532       case 'f':
1533         if (!option_arg.empty())
1534           m_funct_name = option_arg;
1535         break;
1536       case 'c':
1537         if (!option_arg.empty())
1538           m_class_name = option_arg;
1539         break;
1540       case 'h':
1541         if (!option_arg.empty())
1542           m_short_help = option_arg;
1543         break;
1544       case 's':
1545         m_synchronicity =
1546             (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum(
1547                 option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
1548         if (!error.Success())
1549           error.SetErrorStringWithFormat(
1550               "unrecognized value for synchronicity '%s'",
1551               option_arg.str().c_str());
1552         break;
1553       default:
1554         llvm_unreachable("Unimplemented option");
1555       }
1556 
1557       return error;
1558     }
1559 
1560     void OptionParsingStarting(ExecutionContext *execution_context) override {
1561       m_class_name.clear();
1562       m_funct_name.clear();
1563       m_short_help.clear();
1564       m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1565     }
1566 
1567     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1568       return llvm::makeArrayRef(g_script_add_options);
1569     }
1570 
1571     // Instance variables to hold the values for command options.
1572 
1573     std::string m_class_name;
1574     std::string m_funct_name;
1575     std::string m_short_help;
1576     ScriptedCommandSynchronicity m_synchronicity;
1577   };
1578 
1579   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
1580     StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
1581     if (output_sp && interactive) {
1582       output_sp->PutCString(g_python_command_instructions);
1583       output_sp->Flush();
1584     }
1585   }
1586 
1587   void IOHandlerInputComplete(IOHandler &io_handler,
1588                               std::string &data) override {
1589     StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
1590 
1591     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1592     if (interpreter) {
1593 
1594       StringList lines;
1595       lines.SplitIntoLines(data);
1596       if (lines.GetSize() > 0) {
1597         std::string funct_name_str;
1598         if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1599           if (funct_name_str.empty()) {
1600             error_sp->Printf("error: unable to obtain a function name, didn't "
1601                              "add python command.\n");
1602             error_sp->Flush();
1603           } else {
1604             // everything should be fine now, let's add this alias
1605 
1606             CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
1607                 m_interpreter, m_cmd_name, funct_name_str, m_short_help,
1608                 m_synchronicity));
1609 
1610             if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp,
1611                                               true)) {
1612               error_sp->Printf("error: unable to add selected command, didn't "
1613                                "add python command.\n");
1614               error_sp->Flush();
1615             }
1616           }
1617         } else {
1618           error_sp->Printf(
1619               "error: unable to create function, didn't add python command.\n");
1620           error_sp->Flush();
1621         }
1622       } else {
1623         error_sp->Printf("error: empty function, didn't add python command.\n");
1624         error_sp->Flush();
1625       }
1626     } else {
1627       error_sp->Printf(
1628           "error: script interpreter missing, didn't add python command.\n");
1629       error_sp->Flush();
1630     }
1631 
1632     io_handler.SetIsDone(true);
1633   }
1634 
1635 protected:
1636   bool DoExecute(Args &command, CommandReturnObject &result) override {
1637     if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) {
1638       result.AppendError("only scripting language supported for scripted "
1639                          "commands is currently Python");
1640       result.SetStatus(eReturnStatusFailed);
1641       return false;
1642     }
1643 
1644     if (command.GetArgumentCount() != 1) {
1645       result.AppendError("'command script add' requires one argument");
1646       result.SetStatus(eReturnStatusFailed);
1647       return false;
1648     }
1649 
1650     // Store the options in case we get multi-line input
1651     m_cmd_name = command[0].ref();
1652     m_short_help.assign(m_options.m_short_help);
1653     m_synchronicity = m_options.m_synchronicity;
1654 
1655     if (m_options.m_class_name.empty()) {
1656       if (m_options.m_funct_name.empty()) {
1657         m_interpreter.GetPythonCommandsFromIOHandler(
1658             "     ",  // Prompt
1659             *this,    // IOHandlerDelegate
1660             true,     // Run IOHandler in async mode
1661             nullptr); // Baton for the "io_handler" that will be passed back
1662                       // into our IOHandlerDelegate functions
1663       } else {
1664         CommandObjectSP new_cmd(new CommandObjectPythonFunction(
1665             m_interpreter, m_cmd_name, m_options.m_funct_name,
1666             m_options.m_short_help, m_synchronicity));
1667         if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1668           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1669         } else {
1670           result.AppendError("cannot add command");
1671           result.SetStatus(eReturnStatusFailed);
1672         }
1673       }
1674     } else {
1675       ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1676       if (!interpreter) {
1677         result.AppendError("cannot find ScriptInterpreter");
1678         result.SetStatus(eReturnStatusFailed);
1679         return false;
1680       }
1681 
1682       auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1683           m_options.m_class_name.c_str());
1684       if (!cmd_obj_sp) {
1685         result.AppendError("cannot create helper object");
1686         result.SetStatus(eReturnStatusFailed);
1687         return false;
1688       }
1689 
1690       CommandObjectSP new_cmd(new CommandObjectScriptingObject(
1691           m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1692       if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1693         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1694       } else {
1695         result.AppendError("cannot add command");
1696         result.SetStatus(eReturnStatusFailed);
1697       }
1698     }
1699 
1700     return result.Succeeded();
1701   }
1702 
1703   CommandOptions m_options;
1704   std::string m_cmd_name;
1705   std::string m_short_help;
1706   ScriptedCommandSynchronicity m_synchronicity;
1707 };
1708 
1709 // CommandObjectCommandsScriptList
1710 
1711 class CommandObjectCommandsScriptList : public CommandObjectParsed {
1712 public:
1713   CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1714       : CommandObjectParsed(interpreter, "command script list",
1715                             "List defined scripted commands.", nullptr) {}
1716 
1717   ~CommandObjectCommandsScriptList() override = default;
1718 
1719   bool DoExecute(Args &command, CommandReturnObject &result) override {
1720     if (command.GetArgumentCount() != 0) {
1721       result.AppendError("'command script list' doesn't take any arguments");
1722       result.SetStatus(eReturnStatusFailed);
1723       return false;
1724     }
1725 
1726     m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1727 
1728     result.SetStatus(eReturnStatusSuccessFinishResult);
1729 
1730     return true;
1731   }
1732 };
1733 
1734 // CommandObjectCommandsScriptClear
1735 
1736 class CommandObjectCommandsScriptClear : public CommandObjectParsed {
1737 public:
1738   CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1739       : CommandObjectParsed(interpreter, "command script clear",
1740                             "Delete all scripted commands.", nullptr) {}
1741 
1742   ~CommandObjectCommandsScriptClear() override = default;
1743 
1744 protected:
1745   bool DoExecute(Args &command, CommandReturnObject &result) override {
1746     if (command.GetArgumentCount() != 0) {
1747       result.AppendError("'command script clear' doesn't take any arguments");
1748       result.SetStatus(eReturnStatusFailed);
1749       return false;
1750     }
1751 
1752     m_interpreter.RemoveAllUser();
1753 
1754     result.SetStatus(eReturnStatusSuccessFinishResult);
1755 
1756     return true;
1757   }
1758 };
1759 
1760 // CommandObjectCommandsScriptDelete
1761 
1762 class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
1763 public:
1764   CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1765       : CommandObjectParsed(interpreter, "command script delete",
1766                             "Delete a scripted command.", nullptr) {
1767     CommandArgumentEntry arg1;
1768     CommandArgumentData cmd_arg;
1769 
1770     // Define the first (and only) variant of this arg.
1771     cmd_arg.arg_type = eArgTypeCommandName;
1772     cmd_arg.arg_repetition = eArgRepeatPlain;
1773 
1774     // There is only one variant this argument could be; put it into the
1775     // argument entry.
1776     arg1.push_back(cmd_arg);
1777 
1778     // Push the data for the first argument into the m_arguments vector.
1779     m_arguments.push_back(arg1);
1780   }
1781 
1782   ~CommandObjectCommandsScriptDelete() override = default;
1783 
1784 protected:
1785   bool DoExecute(Args &command, CommandReturnObject &result) override {
1786 
1787     if (command.GetArgumentCount() != 1) {
1788       result.AppendError("'command script delete' requires one argument");
1789       result.SetStatus(eReturnStatusFailed);
1790       return false;
1791     }
1792 
1793     auto cmd_name = command[0].ref();
1794 
1795     if (cmd_name.empty() || !m_interpreter.HasUserCommands() ||
1796         !m_interpreter.UserCommandExists(cmd_name)) {
1797       result.AppendErrorWithFormat("command %s not found", command[0].c_str());
1798       result.SetStatus(eReturnStatusFailed);
1799       return false;
1800     }
1801 
1802     m_interpreter.RemoveUser(cmd_name);
1803     result.SetStatus(eReturnStatusSuccessFinishResult);
1804     return true;
1805   }
1806 };
1807 
1808 #pragma mark CommandObjectMultiwordCommandsScript
1809 
1810 // CommandObjectMultiwordCommandsScript
1811 
1812 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
1813 public:
1814   CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1815       : CommandObjectMultiword(
1816             interpreter, "command script",
1817             "Commands for managing custom "
1818             "commands implemented by "
1819             "interpreter scripts.",
1820             "command script <subcommand> [<subcommand-options>]") {
1821     LoadSubCommand("add", CommandObjectSP(
1822                               new CommandObjectCommandsScriptAdd(interpreter)));
1823     LoadSubCommand(
1824         "delete",
1825         CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1826     LoadSubCommand(
1827         "clear",
1828         CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1829     LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1830                                interpreter)));
1831     LoadSubCommand(
1832         "import",
1833         CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1834   }
1835 
1836   ~CommandObjectMultiwordCommandsScript() override = default;
1837 };
1838 
1839 #pragma mark CommandObjectMultiwordCommands
1840 
1841 // CommandObjectMultiwordCommands
1842 
1843 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
1844     CommandInterpreter &interpreter)
1845     : CommandObjectMultiword(interpreter, "command",
1846                              "Commands for managing custom LLDB commands.",
1847                              "command <subcommand> [<subcommand-options>]") {
1848   LoadSubCommand("source",
1849                  CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
1850   LoadSubCommand("alias",
1851                  CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
1852   LoadSubCommand("unalias", CommandObjectSP(
1853                                 new CommandObjectCommandsUnalias(interpreter)));
1854   LoadSubCommand("delete",
1855                  CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
1856   LoadSubCommand(
1857       "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
1858   LoadSubCommand("history", CommandObjectSP(
1859                                 new CommandObjectCommandsHistory(interpreter)));
1860   LoadSubCommand(
1861       "script",
1862       CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
1863 }
1864 
1865 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
1866