]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/source/Commands/CommandObjectCommands.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / source / Commands / CommandObjectCommands.cpp
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;