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