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