1 //===-- CommandObjectCommands.cpp -------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
12 // Other libraries and framework includes
13 #include "llvm/ADT/StringRef.h"
16 #include "CommandObjectCommands.h"
17 #include "CommandObjectHelp.h"
18 #include "lldb/Core/Debugger.h"
19 #include "lldb/Core/IOHandler.h"
20 #include "lldb/Host/OptionParser.h"
21 #include "lldb/Interpreter/CommandHistory.h"
22 #include "lldb/Interpreter/CommandInterpreter.h"
23 #include "lldb/Interpreter/CommandObjectRegexCommand.h"
24 #include "lldb/Interpreter/CommandReturnObject.h"
25 #include "lldb/Interpreter/OptionArgParser.h"
26 #include "lldb/Interpreter/OptionValueBoolean.h"
27 #include "lldb/Interpreter/OptionValueString.h"
28 #include "lldb/Interpreter/OptionValueUInt64.h"
29 #include "lldb/Interpreter/Options.h"
30 #include "lldb/Interpreter/ScriptInterpreter.h"
31 #include "lldb/Utility/Args.h"
32 #include "lldb/Utility/StringList.h"
35 using namespace lldb_private;
37 //-------------------------------------------------------------------------
38 // CommandObjectCommandsSource
39 //-------------------------------------------------------------------------
41 static OptionDefinition g_history_options[] = {
43 { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print." },
44 { LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)." },
45 { LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." },
46 { LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clears the current command history." },
50 class CommandObjectCommandsHistory : public CommandObjectParsed {
52 CommandObjectCommandsHistory(CommandInterpreter &interpreter)
53 : CommandObjectParsed(interpreter, "command history",
54 "Dump the history of commands in this session.\n"
55 "Commands in the history list can be run again "
56 "using \"!<INDEX>\". \"!-<OFFSET>\" will re-run "
57 "the command that is <OFFSET> commands from the end"
58 " of the list (counting the current command).",
62 ~CommandObjectCommandsHistory() override = default;
64 Options *GetOptions() override { return &m_options; }
67 class CommandOptions : public Options {
70 : Options(), m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) {
73 ~CommandOptions() override = default;
75 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
76 ExecutionContext *execution_context) override {
78 const int short_option = m_getopt_table[option_idx].val;
80 switch (short_option) {
82 error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign);
85 if (option_arg == "end") {
86 m_start_idx.SetCurrentValue(UINT64_MAX);
87 m_start_idx.SetOptionWasSet();
89 error = m_start_idx.SetValueFromString(option_arg,
90 eVarSetOperationAssign);
94 m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign);
97 m_clear.SetCurrentValue(true);
98 m_clear.SetOptionWasSet();
101 error.SetErrorStringWithFormat("unrecognized option '%c'",
109 void OptionParsingStarting(ExecutionContext *execution_context) override {
116 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
117 return llvm::makeArrayRef(g_history_options);
120 // Instance variables to hold the values for command options.
122 OptionValueUInt64 m_start_idx;
123 OptionValueUInt64 m_stop_idx;
124 OptionValueUInt64 m_count;
125 OptionValueBoolean m_clear;
128 bool DoExecute(Args &command, CommandReturnObject &result) override {
129 if (m_options.m_clear.GetCurrentValue() &&
130 m_options.m_clear.OptionWasSet()) {
131 m_interpreter.GetCommandHistory().Clear();
132 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
134 if (m_options.m_start_idx.OptionWasSet() &&
135 m_options.m_stop_idx.OptionWasSet() &&
136 m_options.m_count.OptionWasSet()) {
137 result.AppendError("--count, --start-index and --end-index cannot be "
138 "all specified in the same invocation");
139 result.SetStatus(lldb::eReturnStatusFailed);
141 std::pair<bool, uint64_t> start_idx(
142 m_options.m_start_idx.OptionWasSet(),
143 m_options.m_start_idx.GetCurrentValue());
144 std::pair<bool, uint64_t> stop_idx(
145 m_options.m_stop_idx.OptionWasSet(),
146 m_options.m_stop_idx.GetCurrentValue());
147 std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(),
148 m_options.m_count.GetCurrentValue());
150 const CommandHistory &history(m_interpreter.GetCommandHistory());
152 if (start_idx.first && start_idx.second == UINT64_MAX) {
154 start_idx.second = history.GetSize() - count.second;
155 stop_idx.second = history.GetSize() - 1;
156 } else if (stop_idx.first) {
157 start_idx.second = stop_idx.second;
158 stop_idx.second = history.GetSize() - 1;
160 start_idx.second = 0;
161 stop_idx.second = history.GetSize() - 1;
164 if (!start_idx.first && !stop_idx.first && !count.first) {
165 start_idx.second = 0;
166 stop_idx.second = history.GetSize() - 1;
167 } else if (start_idx.first) {
169 stop_idx.second = start_idx.second + count.second - 1;
170 } else if (!stop_idx.first) {
171 stop_idx.second = history.GetSize() - 1;
173 } else if (stop_idx.first) {
175 if (stop_idx.second >= count.second)
176 start_idx.second = stop_idx.second - count.second + 1;
178 start_idx.second = 0;
180 } else /* if (count.first) */
182 start_idx.second = 0;
183 stop_idx.second = count.second - 1;
186 history.Dump(result.GetOutputStream(), start_idx.second,
190 return result.Succeeded();
193 CommandOptions m_options;
196 //-------------------------------------------------------------------------
197 // CommandObjectCommandsSource
198 //-------------------------------------------------------------------------
200 static OptionDefinition g_source_options[] = {
202 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error." },
203 { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue." },
204 { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing." },
208 class CommandObjectCommandsSource : public CommandObjectParsed {
210 CommandObjectCommandsSource(CommandInterpreter &interpreter)
211 : CommandObjectParsed(
212 interpreter, "command source",
213 "Read and execute LLDB commands from the file <filename>.",
216 CommandArgumentEntry arg;
217 CommandArgumentData file_arg;
219 // Define the first (and only) variant of this arg.
220 file_arg.arg_type = eArgTypeFilename;
221 file_arg.arg_repetition = eArgRepeatPlain;
223 // There is only one variant this argument could be; put it into the
225 arg.push_back(file_arg);
227 // Push the data for the first argument into the m_arguments vector.
228 m_arguments.push_back(arg);
231 ~CommandObjectCommandsSource() override = default;
233 const char *GetRepeatCommand(Args ¤t_command_args,
234 uint32_t index) override {
238 int HandleArgumentCompletion(
239 CompletionRequest &request,
240 OptionElementVector &opt_element_vector) override {
241 CommandCompletions::InvokeCommonCompletionCallbacks(
242 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
244 return request.GetMatches().GetSize();
247 Options *GetOptions() override { return &m_options; }
250 class CommandOptions : public Options {
253 : Options(), m_stop_on_error(true), m_silent_run(false),
254 m_stop_on_continue(true) {}
256 ~CommandOptions() override = default;
258 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
259 ExecutionContext *execution_context) override {
261 const int short_option = m_getopt_table[option_idx].val;
263 switch (short_option) {
265 error = m_stop_on_error.SetValueFromString(option_arg);
269 error = m_stop_on_continue.SetValueFromString(option_arg);
273 error = m_silent_run.SetValueFromString(option_arg);
277 error.SetErrorStringWithFormat("unrecognized option '%c'",
285 void OptionParsingStarting(ExecutionContext *execution_context) override {
286 m_stop_on_error.Clear();
287 m_silent_run.Clear();
288 m_stop_on_continue.Clear();
291 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
292 return llvm::makeArrayRef(g_source_options);
295 // Instance variables to hold the values for command options.
297 OptionValueBoolean m_stop_on_error;
298 OptionValueBoolean m_silent_run;
299 OptionValueBoolean m_stop_on_continue;
302 bool DoExecute(Args &command, CommandReturnObject &result) override {
303 if (command.GetArgumentCount() != 1) {
304 result.AppendErrorWithFormat(
305 "'%s' takes exactly one executable filename argument.\n",
306 GetCommandName().str().c_str());
307 result.SetStatus(eReturnStatusFailed);
311 FileSpec cmd_file(command[0].ref, true);
312 ExecutionContext *exe_ctx = nullptr; // Just use the default context.
314 // If any options were set, then use them
315 if (m_options.m_stop_on_error.OptionWasSet() ||
316 m_options.m_silent_run.OptionWasSet() ||
317 m_options.m_stop_on_continue.OptionWasSet()) {
318 // Use user set settings
319 CommandInterpreterRunOptions options;
320 options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue());
321 options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue());
322 options.SetEchoCommands(!m_options.m_silent_run.GetCurrentValue());
323 options.SetPrintResults(!m_options.m_silent_run.GetCurrentValue());
325 m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result);
327 // No options were set, inherit any settings from nested "command source"
328 // commands, or set to sane default settings...
329 CommandInterpreterRunOptions options;
330 m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result);
332 return result.Succeeded();
335 CommandOptions m_options;
338 #pragma mark CommandObjectCommandsAlias
339 //-------------------------------------------------------------------------
340 // CommandObjectCommandsAlias
341 //-------------------------------------------------------------------------
343 static OptionDefinition g_alias_options[] = {
345 { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command" },
346 { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command" },
350 static const char *g_python_command_instructions =
351 "Enter your Python command(s). Type 'DONE' to end.\n"
352 "You must define a Python function with this signature:\n"
353 "def my_command_impl(debugger, args, result, internal_dict):\n";
355 class CommandObjectCommandsAlias : public CommandObjectRaw {
357 class CommandOptions : public OptionGroup {
359 CommandOptions() : OptionGroup(), m_help(), m_long_help() {}
361 ~CommandOptions() override = default;
363 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
364 return llvm::makeArrayRef(g_alias_options);
367 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
368 ExecutionContext *execution_context) override {
371 const int short_option = GetDefinitions()[option_idx].short_option;
372 std::string option_str(option_value);
374 switch (short_option) {
376 m_help.SetCurrentValue(option_str);
377 m_help.SetOptionWasSet();
381 m_long_help.SetCurrentValue(option_str);
382 m_long_help.SetOptionWasSet();
386 error.SetErrorStringWithFormat("invalid short option character '%c'",
394 void OptionParsingStarting(ExecutionContext *execution_context) override {
399 OptionValueString m_help;
400 OptionValueString m_long_help;
403 OptionGroupOptions m_option_group;
404 CommandOptions m_command_options;
407 Options *GetOptions() override { return &m_option_group; }
409 CommandObjectCommandsAlias(CommandInterpreter &interpreter)
411 interpreter, "command alias",
412 "Define a custom command in terms of an existing command."),
413 m_option_group(), m_command_options() {
414 m_option_group.Append(&m_command_options);
415 m_option_group.Finalize();
418 "'alias' allows the user to create a short-cut or abbreviation for long \
419 commands, multi-word commands, and commands that take particular options. \
420 Below are some simple examples of how one might use the 'alias' command:"
423 (lldb) command alias sc script
425 Creates the abbreviation 'sc' for the 'script' command.
427 (lldb) command alias bp breakpoint
430 " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \
431 breakpoint commands are two-word commands, the user would still need to \
432 enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
435 (lldb) command alias bpl breakpoint list
437 Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
440 "An alias can include some options for the command, with the values either \
441 filled in at the time the alias is created, or specified as positional \
442 arguments, to be filled in when the alias is invoked. The following example \
443 shows how to create aliases with options:"
446 (lldb) command alias bfl breakpoint set -f %1 -l %2
449 " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
450 options already part of the alias. So if the user wants to set a breakpoint \
451 by file and line without explicitly having to use the -f and -l options, the \
452 user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \
453 for the actual arguments that will be passed when the alias command is used. \
454 The number in the placeholder refers to the position/order the actual value \
455 occupies when the alias is used. All the occurrences of '%1' in the alias \
456 will be replaced with the first argument, all the occurrences of '%2' in the \
457 alias will be replaced with the second argument, and so on. This also allows \
458 actual arguments to be used multiple times within an alias (see 'process \
459 launch' example below)."
463 "Note: the positional arguments must substitute as whole words in the resultant \
464 command, so you can't at present do something like this to append the file extension \
468 (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
471 "For more complex aliasing, use the \"command regex\" command instead. In the \
472 'bfl' case above, the actual file value will be filled in with the first argument \
473 following 'bfl' and the actual line number value will be filled in with the second \
474 argument. The user would use this alias as follows:"
477 (lldb) command alias bfl breakpoint set -f %1 -l %2
478 (lldb) bfl my-file.c 137
480 This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
484 (lldb) command alias pltty process launch -s -o %1 -e %1
485 (lldb) pltty /dev/tty0
487 Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
490 "If the user always wanted to pass the same value to a particular option, the \
491 alias could be defined with that value directly in the alias as a constant, \
492 rather than using a positional placeholder:"
495 (lldb) command alias bl3 breakpoint set -f %1 -l 3
497 Always sets a breakpoint on line 3 of whatever file is indicated.)");
499 CommandArgumentEntry arg1;
500 CommandArgumentEntry arg2;
501 CommandArgumentEntry arg3;
502 CommandArgumentData alias_arg;
503 CommandArgumentData cmd_arg;
504 CommandArgumentData options_arg;
506 // Define the first (and only) variant of this arg.
507 alias_arg.arg_type = eArgTypeAliasName;
508 alias_arg.arg_repetition = eArgRepeatPlain;
510 // There is only one variant this argument could be; put it into the
512 arg1.push_back(alias_arg);
514 // Define the first (and only) variant of this arg.
515 cmd_arg.arg_type = eArgTypeCommandName;
516 cmd_arg.arg_repetition = eArgRepeatPlain;
518 // There is only one variant this argument could be; put it into the
520 arg2.push_back(cmd_arg);
522 // Define the first (and only) variant of this arg.
523 options_arg.arg_type = eArgTypeAliasOptions;
524 options_arg.arg_repetition = eArgRepeatOptional;
526 // There is only one variant this argument could be; put it into the
528 arg3.push_back(options_arg);
530 // Push the data for the first argument into the m_arguments vector.
531 m_arguments.push_back(arg1);
532 m_arguments.push_back(arg2);
533 m_arguments.push_back(arg3);
536 ~CommandObjectCommandsAlias() override = default;
539 bool DoExecute(llvm::StringRef raw_command_line,
540 CommandReturnObject &result) override {
541 if (raw_command_line.empty()) {
542 result.AppendError("'command alias' requires at least two arguments");
546 ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
547 m_option_group.NotifyOptionParsingStarting(&exe_ctx);
549 OptionsWithRaw args_with_suffix(raw_command_line);
550 const char *remainder = args_with_suffix.GetRawPart().c_str();
552 if (args_with_suffix.HasArgs())
553 if (!ParseOptionsAndNotify(args_with_suffix.GetArgs(), result,
554 m_option_group, exe_ctx))
557 llvm::StringRef raw_command_string(remainder);
558 Args args(raw_command_string);
560 if (args.GetArgumentCount() < 2) {
561 result.AppendError("'command alias' requires at least two arguments");
562 result.SetStatus(eReturnStatusFailed);
566 // Get the alias command.
568 auto alias_command = args[0].ref;
569 if (alias_command.startswith("-")) {
570 result.AppendError("aliases starting with a dash are not supported");
571 if (alias_command == "--help" || alias_command == "--long-help") {
572 result.AppendWarning("if trying to pass options to 'command alias' add "
573 "a -- at the end of the options");
575 result.SetStatus(eReturnStatusFailed);
579 // Strip the new alias name off 'raw_command_string' (leave it on args,
580 // which gets passed to 'Execute', which does the stripping itself.
581 size_t pos = raw_command_string.find(alias_command);
583 raw_command_string = raw_command_string.substr(alias_command.size());
584 pos = raw_command_string.find_first_not_of(' ');
585 if ((pos != std::string::npos) && (pos > 0))
586 raw_command_string = raw_command_string.substr(pos);
588 result.AppendError("Error parsing command string. No alias created.");
589 result.SetStatus(eReturnStatusFailed);
593 // Verify that the command is alias-able.
594 if (m_interpreter.CommandExists(alias_command)) {
595 result.AppendErrorWithFormat(
596 "'%s' is a permanent debugger command and cannot be redefined.\n",
598 result.SetStatus(eReturnStatusFailed);
602 // Get CommandObject that is being aliased. The command name is read from
603 // the front of raw_command_string. raw_command_string is returned with the
604 // name of the command object stripped off the front.
605 llvm::StringRef original_raw_command_string = raw_command_string;
606 CommandObject *cmd_obj =
607 m_interpreter.GetCommandObjectForCommand(raw_command_string);
610 result.AppendErrorWithFormat("invalid command given to 'command alias'. "
611 "'%s' does not begin with a valid command."
612 " No alias created.",
613 original_raw_command_string.str().c_str());
614 result.SetStatus(eReturnStatusFailed);
616 } else if (!cmd_obj->WantsRawCommandString()) {
617 // Note that args was initialized with the original command, and has not
618 // been updated to this point. Therefore can we pass it to the version of
619 // Execute that does not need/expect raw input in the alias.
620 return HandleAliasingNormalCommand(args, result);
622 return HandleAliasingRawCommand(alias_command, raw_command_string,
625 return result.Succeeded();
628 bool HandleAliasingRawCommand(llvm::StringRef alias_command,
629 llvm::StringRef raw_command_string,
630 CommandObject &cmd_obj,
631 CommandReturnObject &result) {
632 // Verify & handle any options/arguments passed to the alias command
634 OptionArgVectorSP option_arg_vector_sp =
635 OptionArgVectorSP(new OptionArgVector);
637 if (CommandObjectSP cmd_obj_sp =
638 m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) {
639 if (m_interpreter.AliasExists(alias_command) ||
640 m_interpreter.UserCommandExists(alias_command)) {
641 result.AppendWarningWithFormat(
642 "Overwriting existing definition for '%s'.\n",
643 alias_command.str().c_str());
645 if (CommandAlias *alias = m_interpreter.AddAlias(
646 alias_command, cmd_obj_sp, raw_command_string)) {
647 if (m_command_options.m_help.OptionWasSet())
648 alias->SetHelp(m_command_options.m_help.GetCurrentValue());
649 if (m_command_options.m_long_help.OptionWasSet())
650 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
651 result.SetStatus(eReturnStatusSuccessFinishNoResult);
653 result.AppendError("Unable to create requested alias.\n");
654 result.SetStatus(eReturnStatusFailed);
658 result.AppendError("Unable to create requested alias.\n");
659 result.SetStatus(eReturnStatusFailed);
662 return result.Succeeded();
665 bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
666 size_t argc = args.GetArgumentCount();
669 result.AppendError("'command alias' requires at least two arguments");
670 result.SetStatus(eReturnStatusFailed);
674 // Save these in std::strings since we're going to shift them off.
675 const std::string alias_command(args[0].ref);
676 const std::string actual_command(args[1].ref);
678 args.Shift(); // Shift the alias command word off the argument vector.
679 args.Shift(); // Shift the old command word off the argument vector.
681 // Verify that the command is alias'able, and get the appropriate command
684 if (m_interpreter.CommandExists(alias_command)) {
685 result.AppendErrorWithFormat(
686 "'%s' is a permanent debugger command and cannot be redefined.\n",
687 alias_command.c_str());
688 result.SetStatus(eReturnStatusFailed);
692 CommandObjectSP command_obj_sp(
693 m_interpreter.GetCommandSPExact(actual_command, true));
694 CommandObjectSP subcommand_obj_sp;
695 bool use_subcommand = false;
696 if (!command_obj_sp) {
697 result.AppendErrorWithFormat("'%s' is not an existing command.\n",
698 actual_command.c_str());
699 result.SetStatus(eReturnStatusFailed);
702 CommandObject *cmd_obj = command_obj_sp.get();
703 CommandObject *sub_cmd_obj = nullptr;
704 OptionArgVectorSP option_arg_vector_sp =
705 OptionArgVectorSP(new OptionArgVector);
707 while (cmd_obj->IsMultiwordObject() && !args.empty()) {
708 auto sub_command = args[0].ref;
709 assert(!sub_command.empty());
710 subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command);
711 if (!subcommand_obj_sp) {
712 result.AppendErrorWithFormat(
713 "'%s' is not a valid sub-command of '%s'. "
714 "Unable to create alias.\n",
715 args[0].c_str(), actual_command.c_str());
716 result.SetStatus(eReturnStatusFailed);
720 sub_cmd_obj = subcommand_obj_sp.get();
721 use_subcommand = true;
722 args.Shift(); // Shift the sub_command word off the argument vector.
723 cmd_obj = sub_cmd_obj;
726 // Verify & handle any options/arguments passed to the alias command
728 std::string args_string;
731 CommandObjectSP tmp_sp =
732 m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false);
734 tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName(),
737 args.GetCommandString(args_string);
740 if (m_interpreter.AliasExists(alias_command) ||
741 m_interpreter.UserCommandExists(alias_command)) {
742 result.AppendWarningWithFormat(
743 "Overwriting existing definition for '%s'.\n", alias_command.c_str());
746 if (CommandAlias *alias = m_interpreter.AddAlias(
747 alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp,
749 if (m_command_options.m_help.OptionWasSet())
750 alias->SetHelp(m_command_options.m_help.GetCurrentValue());
751 if (m_command_options.m_long_help.OptionWasSet())
752 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
753 result.SetStatus(eReturnStatusSuccessFinishNoResult);
755 result.AppendError("Unable to create requested alias.\n");
756 result.SetStatus(eReturnStatusFailed);
760 return result.Succeeded();
764 #pragma mark CommandObjectCommandsUnalias
765 //-------------------------------------------------------------------------
766 // CommandObjectCommandsUnalias
767 //-------------------------------------------------------------------------
769 class CommandObjectCommandsUnalias : public CommandObjectParsed {
771 CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
772 : CommandObjectParsed(
773 interpreter, "command unalias",
774 "Delete one or more custom commands defined by 'command alias'.",
776 CommandArgumentEntry arg;
777 CommandArgumentData alias_arg;
779 // Define the first (and only) variant of this arg.
780 alias_arg.arg_type = eArgTypeAliasName;
781 alias_arg.arg_repetition = eArgRepeatPlain;
783 // There is only one variant this argument could be; put it into the
785 arg.push_back(alias_arg);
787 // Push the data for the first argument into the m_arguments vector.
788 m_arguments.push_back(arg);
791 ~CommandObjectCommandsUnalias() override = default;
794 bool DoExecute(Args &args, CommandReturnObject &result) override {
795 CommandObject::CommandMap::iterator pos;
796 CommandObject *cmd_obj;
799 result.AppendError("must call 'unalias' with a valid alias");
800 result.SetStatus(eReturnStatusFailed);
804 auto command_name = args[0].ref;
805 cmd_obj = m_interpreter.GetCommandObject(command_name);
807 result.AppendErrorWithFormat(
808 "'%s' is not a known command.\nTry 'help' to see a "
809 "current list of commands.\n",
811 result.SetStatus(eReturnStatusFailed);
815 if (m_interpreter.CommandExists(command_name)) {
816 if (cmd_obj->IsRemovable()) {
817 result.AppendErrorWithFormat(
818 "'%s' is not an alias, it is a debugger command which can be "
819 "removed using the 'command delete' command.\n",
822 result.AppendErrorWithFormat(
823 "'%s' is a permanent debugger command and cannot be removed.\n",
826 result.SetStatus(eReturnStatusFailed);
830 if (!m_interpreter.RemoveAlias(command_name)) {
831 if (m_interpreter.AliasExists(command_name))
832 result.AppendErrorWithFormat(
833 "Error occurred while attempting to unalias '%s'.\n",
836 result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
838 result.SetStatus(eReturnStatusFailed);
842 result.SetStatus(eReturnStatusSuccessFinishNoResult);
843 return result.Succeeded();
847 #pragma mark CommandObjectCommandsDelete
848 //-------------------------------------------------------------------------
849 // CommandObjectCommandsDelete
850 //-------------------------------------------------------------------------
852 class CommandObjectCommandsDelete : public CommandObjectParsed {
854 CommandObjectCommandsDelete(CommandInterpreter &interpreter)
855 : CommandObjectParsed(
856 interpreter, "command delete",
857 "Delete one or more custom commands defined by 'command regex'.",
859 CommandArgumentEntry arg;
860 CommandArgumentData alias_arg;
862 // Define the first (and only) variant of this arg.
863 alias_arg.arg_type = eArgTypeCommandName;
864 alias_arg.arg_repetition = eArgRepeatPlain;
866 // There is only one variant this argument could be; put it into the
868 arg.push_back(alias_arg);
870 // Push the data for the first argument into the m_arguments vector.
871 m_arguments.push_back(arg);
874 ~CommandObjectCommandsDelete() override = default;
877 bool DoExecute(Args &args, CommandReturnObject &result) override {
878 CommandObject::CommandMap::iterator pos;
881 result.AppendErrorWithFormat("must call '%s' with one or more valid user "
882 "defined regular expression command names",
883 GetCommandName().str().c_str());
884 result.SetStatus(eReturnStatusFailed);
887 auto command_name = args[0].ref;
888 if (!m_interpreter.CommandExists(command_name)) {
889 StreamString error_msg_stream;
890 const bool generate_apropos = true;
891 const bool generate_type_lookup = false;
892 CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
893 &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(),
894 generate_apropos, generate_type_lookup);
895 result.AppendError(error_msg_stream.GetString());
896 result.SetStatus(eReturnStatusFailed);
900 if (!m_interpreter.RemoveCommand(command_name)) {
901 result.AppendErrorWithFormat(
902 "'%s' is a permanent debugger command and cannot be removed.\n",
904 result.SetStatus(eReturnStatusFailed);
908 result.SetStatus(eReturnStatusSuccessFinishNoResult);
913 //-------------------------------------------------------------------------
914 // CommandObjectCommandsAddRegex
915 //-------------------------------------------------------------------------
917 static OptionDefinition g_regex_options[] = {
919 { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command." },
920 { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." },
924 #pragma mark CommandObjectCommandsAddRegex
926 class CommandObjectCommandsAddRegex : public CommandObjectParsed,
927 public IOHandlerDelegateMultiline {
929 CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
930 : CommandObjectParsed(
931 interpreter, "command regex", "Define a custom command in terms of "
932 "existing commands by matching "
933 "regular expressions.",
934 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
935 IOHandlerDelegateMultiline("",
936 IOHandlerDelegate::Completion::LLDBCommand),
941 "This command allows the user to create powerful regular expression commands \
942 with substitutions. The regular expressions and substitutions are specified \
943 using the regular expression substitution format of:"
949 "<regex> is a regular expression that can use parenthesis to capture regular \
950 expression input and substitute the captured matches in the output using %1 \
951 for the first match, %2 for the second, and so on."
955 "The regular expressions can all be specified on the command line if more than \
956 one argument is provided. If just the command name is provided on the command \
957 line, then the regular expressions and substitutions can be entered on separate \
958 lines, followed by an empty line to terminate the command definition."
964 "The following example will define a regular expression command named 'f' that \
965 will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
966 a number follows 'f':"
969 (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
972 ~CommandObjectCommandsAddRegex() override = default;
975 void IOHandlerActivated(IOHandler &io_handler) override {
976 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
978 output_sp->PutCString("Enter one of more sed substitution commands in "
979 "the form: 's/<regex>/<subst>/'.\nTerminate the "
980 "substitution list with an empty line.\n");
985 void IOHandlerInputComplete(IOHandler &io_handler,
986 std::string &data) override {
987 io_handler.SetIsDone(true);
988 if (m_regex_cmd_ap) {
990 if (lines.SplitIntoLines(data)) {
991 const size_t num_lines = lines.GetSize();
992 bool check_only = false;
993 for (size_t i = 0; i < num_lines; ++i) {
994 llvm::StringRef bytes_strref(lines[i]);
995 Status error = AppendRegexSubstitution(bytes_strref, check_only);
997 if (!m_interpreter.GetDebugger()
998 .GetCommandInterpreter()
999 .GetBatchCommandMode()) {
1000 StreamSP out_stream =
1001 m_interpreter.GetDebugger().GetAsyncOutputStream();
1002 out_stream->Printf("error: %s\n", error.AsCString());
1007 if (m_regex_cmd_ap->HasRegexEntries()) {
1008 CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1009 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1014 bool DoExecute(Args &command, CommandReturnObject &result) override {
1015 const size_t argc = command.GetArgumentCount();
1017 result.AppendError("usage: 'command regex <command-name> "
1018 "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
1019 result.SetStatus(eReturnStatusFailed);
1024 auto name = command[0].ref;
1025 m_regex_cmd_ap = llvm::make_unique<CommandObjectRegexCommand>(
1026 m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0,
1030 Debugger &debugger = m_interpreter.GetDebugger();
1031 bool color_prompt = debugger.GetUseColor();
1032 const bool multiple_lines = true; // Get multiple lines
1033 IOHandlerSP io_handler_sp(new IOHandlerEditline(
1034 debugger, IOHandler::Type::Other,
1035 "lldb-regex", // Name of input reader for history
1036 llvm::StringRef("> "), // Prompt
1037 llvm::StringRef(), // Continuation prompt
1038 multiple_lines, color_prompt,
1039 0, // Don't show line numbers
1042 if (io_handler_sp) {
1043 debugger.PushIOHandler(io_handler_sp);
1044 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1047 for (auto &entry : command.entries().drop_front()) {
1048 bool check_only = false;
1049 error = AppendRegexSubstitution(entry.ref, check_only);
1054 if (error.Success()) {
1055 AddRegexCommandToInterpreter();
1059 result.AppendError(error.AsCString());
1060 result.SetStatus(eReturnStatusFailed);
1063 return result.Succeeded();
1066 Status AppendRegexSubstitution(const llvm::StringRef ®ex_sed,
1070 if (!m_regex_cmd_ap) {
1071 error.SetErrorStringWithFormat(
1072 "invalid regular expression command object for: '%.*s'",
1073 (int)regex_sed.size(), regex_sed.data());
1077 size_t regex_sed_size = regex_sed.size();
1079 if (regex_sed_size <= 1) {
1080 error.SetErrorStringWithFormat(
1081 "regular expression substitution string is too short: '%.*s'",
1082 (int)regex_sed.size(), regex_sed.data());
1086 if (regex_sed[0] != 's') {
1087 error.SetErrorStringWithFormat("regular expression substitution string "
1088 "doesn't start with 's': '%.*s'",
1089 (int)regex_sed.size(), regex_sed.data());
1092 const size_t first_separator_char_pos = 1;
1093 // use the char that follows 's' as the regex separator character so we can
1094 // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
1095 const char separator_char = regex_sed[first_separator_char_pos];
1096 const size_t second_separator_char_pos =
1097 regex_sed.find(separator_char, first_separator_char_pos + 1);
1099 if (second_separator_char_pos == std::string::npos) {
1100 error.SetErrorStringWithFormat(
1101 "missing second '%c' separator char after '%.*s' in '%.*s'",
1103 (int)(regex_sed.size() - first_separator_char_pos - 1),
1104 regex_sed.data() + (first_separator_char_pos + 1),
1105 (int)regex_sed.size(), regex_sed.data());
1109 const size_t third_separator_char_pos =
1110 regex_sed.find(separator_char, second_separator_char_pos + 1);
1112 if (third_separator_char_pos == std::string::npos) {
1113 error.SetErrorStringWithFormat(
1114 "missing third '%c' separator char after '%.*s' in '%.*s'",
1116 (int)(regex_sed.size() - second_separator_char_pos - 1),
1117 regex_sed.data() + (second_separator_char_pos + 1),
1118 (int)regex_sed.size(), regex_sed.data());
1122 if (third_separator_char_pos != regex_sed_size - 1) {
1123 // Make sure that everything that follows the last regex separator char
1124 if (regex_sed.find_first_not_of("\t\n\v\f\r ",
1125 third_separator_char_pos + 1) !=
1126 std::string::npos) {
1127 error.SetErrorStringWithFormat(
1128 "extra data found after the '%.*s' regular expression substitution "
1130 (int)third_separator_char_pos + 1, regex_sed.data(),
1131 (int)(regex_sed.size() - third_separator_char_pos - 1),
1132 regex_sed.data() + (third_separator_char_pos + 1));
1135 } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
1136 error.SetErrorStringWithFormat(
1137 "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1138 separator_char, separator_char, separator_char, (int)regex_sed.size(),
1141 } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
1142 error.SetErrorStringWithFormat(
1143 "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1144 separator_char, separator_char, separator_char, (int)regex_sed.size(),
1150 std::string regex(regex_sed.substr(first_separator_char_pos + 1,
1151 second_separator_char_pos -
1152 first_separator_char_pos - 1));
1153 std::string subst(regex_sed.substr(second_separator_char_pos + 1,
1154 third_separator_char_pos -
1155 second_separator_char_pos - 1));
1156 m_regex_cmd_ap->AddRegexCommand(regex.c_str(), subst.c_str());
1161 void AddRegexCommandToInterpreter() {
1162 if (m_regex_cmd_ap) {
1163 if (m_regex_cmd_ap->HasRegexEntries()) {
1164 CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1165 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1171 std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
1173 class CommandOptions : public Options {
1175 CommandOptions() : Options() {}
1177 ~CommandOptions() override = default;
1179 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1180 ExecutionContext *execution_context) override {
1182 const int short_option = m_getopt_table[option_idx].val;
1184 switch (short_option) {
1186 m_help.assign(option_arg);
1189 m_syntax.assign(option_arg);
1192 error.SetErrorStringWithFormat("unrecognized option '%c'",
1200 void OptionParsingStarting(ExecutionContext *execution_context) override {
1205 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1206 return llvm::makeArrayRef(g_regex_options);
1209 // TODO: Convert these functions to return StringRefs.
1210 const char *GetHelp() {
1211 return (m_help.empty() ? nullptr : m_help.c_str());
1214 const char *GetSyntax() {
1215 return (m_syntax.empty() ? nullptr : m_syntax.c_str());
1219 // Instance variables to hold the values for command options.
1222 std::string m_syntax;
1225 Options *GetOptions() override { return &m_options; }
1227 CommandOptions m_options;
1230 class CommandObjectPythonFunction : public CommandObjectRaw {
1232 CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
1233 std::string funct, std::string help,
1234 ScriptedCommandSynchronicity synch)
1235 : CommandObjectRaw(interpreter, name),
1236 m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) {
1240 StreamString stream;
1241 stream.Printf("For more information run 'help %s'", name.c_str());
1242 SetHelp(stream.GetString());
1246 ~CommandObjectPythonFunction() override = default;
1248 bool IsRemovable() const override { return true; }
1250 const std::string &GetFunctionName() { return m_function_name; }
1252 ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1254 llvm::StringRef GetHelpLong() override {
1255 if (m_fetched_help_long)
1256 return CommandObjectRaw::GetHelpLong();
1258 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1260 return CommandObjectRaw::GetHelpLong();
1262 std::string docstring;
1263 m_fetched_help_long =
1264 scripter->GetDocumentationForItem(m_function_name.c_str(), docstring);
1265 if (!docstring.empty())
1266 SetHelpLong(docstring);
1267 return CommandObjectRaw::GetHelpLong();
1271 bool DoExecute(llvm::StringRef raw_command_line,
1272 CommandReturnObject &result) override {
1273 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1277 result.SetStatus(eReturnStatusInvalid);
1280 !scripter->RunScriptBasedCommand(m_function_name.c_str(),
1281 raw_command_line, m_synchro, result,
1282 error, m_exe_ctx)) {
1283 result.AppendError(error.AsCString());
1284 result.SetStatus(eReturnStatusFailed);
1286 // Don't change the status if the command already set it...
1287 if (result.GetStatus() == eReturnStatusInvalid) {
1288 if (result.GetOutputData().empty())
1289 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1291 result.SetStatus(eReturnStatusSuccessFinishResult);
1295 return result.Succeeded();
1299 std::string m_function_name;
1300 ScriptedCommandSynchronicity m_synchro;
1301 bool m_fetched_help_long;
1304 class CommandObjectScriptingObject : public CommandObjectRaw {
1306 CommandObjectScriptingObject(CommandInterpreter &interpreter,
1308 StructuredData::GenericSP cmd_obj_sp,
1309 ScriptedCommandSynchronicity synch)
1310 : CommandObjectRaw(interpreter, name),
1311 m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false),
1312 m_fetched_help_long(false) {
1313 StreamString stream;
1314 stream.Printf("For more information run 'help %s'", name.c_str());
1315 SetHelp(stream.GetString());
1316 if (ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter())
1317 GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
1320 ~CommandObjectScriptingObject() override = default;
1322 bool IsRemovable() const override { return true; }
1324 StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; }
1326 ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1328 llvm::StringRef GetHelp() override {
1329 if (m_fetched_help_short)
1330 return CommandObjectRaw::GetHelp();
1331 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1333 return CommandObjectRaw::GetHelp();
1334 std::string docstring;
1335 m_fetched_help_short =
1336 scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
1337 if (!docstring.empty())
1340 return CommandObjectRaw::GetHelp();
1343 llvm::StringRef GetHelpLong() override {
1344 if (m_fetched_help_long)
1345 return CommandObjectRaw::GetHelpLong();
1347 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1349 return CommandObjectRaw::GetHelpLong();
1351 std::string docstring;
1352 m_fetched_help_long =
1353 scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
1354 if (!docstring.empty())
1355 SetHelpLong(docstring);
1356 return CommandObjectRaw::GetHelpLong();
1360 bool DoExecute(llvm::StringRef raw_command_line,
1361 CommandReturnObject &result) override {
1362 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1366 result.SetStatus(eReturnStatusInvalid);
1369 !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1370 m_synchro, result, error, m_exe_ctx)) {
1371 result.AppendError(error.AsCString());
1372 result.SetStatus(eReturnStatusFailed);
1374 // Don't change the status if the command already set it...
1375 if (result.GetStatus() == eReturnStatusInvalid) {
1376 if (result.GetOutputData().empty())
1377 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1379 result.SetStatus(eReturnStatusSuccessFinishResult);
1383 return result.Succeeded();
1387 StructuredData::GenericSP m_cmd_obj_sp;
1388 ScriptedCommandSynchronicity m_synchro;
1389 bool m_fetched_help_short : 1;
1390 bool m_fetched_help_long : 1;
1393 //-------------------------------------------------------------------------
1394 // CommandObjectCommandsScriptImport
1395 //-------------------------------------------------------------------------
1397 OptionDefinition g_script_import_options[] = {
1399 { LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not." },
1403 class CommandObjectCommandsScriptImport : public CommandObjectParsed {
1405 CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1406 : CommandObjectParsed(interpreter, "command script import",
1407 "Import a scripting module in LLDB.", nullptr),
1409 CommandArgumentEntry arg1;
1410 CommandArgumentData cmd_arg;
1412 // Define the first (and only) variant of this arg.
1413 cmd_arg.arg_type = eArgTypeFilename;
1414 cmd_arg.arg_repetition = eArgRepeatPlus;
1416 // There is only one variant this argument could be; put it into the
1418 arg1.push_back(cmd_arg);
1420 // Push the data for the first argument into the m_arguments vector.
1421 m_arguments.push_back(arg1);
1424 ~CommandObjectCommandsScriptImport() override = default;
1426 int HandleArgumentCompletion(
1427 CompletionRequest &request,
1428 OptionElementVector &opt_element_vector) override {
1429 CommandCompletions::InvokeCommonCompletionCallbacks(
1430 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
1432 return request.GetMatches().GetSize();
1435 Options *GetOptions() override { return &m_options; }
1438 class CommandOptions : public Options {
1440 CommandOptions() : Options() {}
1442 ~CommandOptions() override = default;
1444 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1445 ExecutionContext *execution_context) override {
1447 const int short_option = m_getopt_table[option_idx].val;
1449 switch (short_option) {
1451 m_allow_reload = true;
1454 error.SetErrorStringWithFormat("unrecognized option '%c'",
1462 void OptionParsingStarting(ExecutionContext *execution_context) override {
1463 m_allow_reload = true;
1466 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1467 return llvm::makeArrayRef(g_script_import_options);
1470 // Instance variables to hold the values for command options.
1472 bool m_allow_reload;
1475 bool DoExecute(Args &command, CommandReturnObject &result) override {
1476 if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1477 lldb::eScriptLanguagePython) {
1478 result.AppendError("only scripting language supported for module "
1479 "importing is currently Python");
1480 result.SetStatus(eReturnStatusFailed);
1484 if (command.empty()) {
1485 result.AppendError("command script import needs one or more arguments");
1486 result.SetStatus(eReturnStatusFailed);
1490 for (auto &entry : command.entries()) {
1493 const bool init_session = true;
1494 // FIXME: this is necessary because CommandObject::CheckRequirements()
1495 // assumes that commands won't ever be recursively invoked, but it's
1496 // actually possible to craft a Python script that does other "command
1497 // script imports" in __lldb_init_module the real fix is to have
1498 // recursive commands possible with a CommandInvocation object separate
1499 // from the CommandObject itself, so that recursive command invocations
1500 // won't stomp on each other (wrt to execution contents, options, and
1503 if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(
1504 entry.c_str(), m_options.m_allow_reload, init_session, error)) {
1505 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1507 result.AppendErrorWithFormat("module importing failed: %s",
1509 result.SetStatus(eReturnStatusFailed);
1513 return result.Succeeded();
1516 CommandOptions m_options;
1519 //-------------------------------------------------------------------------
1520 // CommandObjectCommandsScriptAdd
1521 //-------------------------------------------------------------------------
1523 static OptionEnumValueElement g_script_synchro_type[] = {
1524 {eScriptedCommandSynchronicitySynchronous, "synchronous",
1526 {eScriptedCommandSynchronicityAsynchronous, "asynchronous",
1527 "Run asynchronous"},
1528 {eScriptedCommandSynchronicityCurrentValue, "current",
1529 "Do not alter current setting"},
1530 {0, nullptr, nullptr}};
1532 static OptionDefinition g_script_add_options[] = {
1534 { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name." },
1535 { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name." },
1536 { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command." },
1537 { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, nullptr, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system." },
1541 class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1542 public IOHandlerDelegateMultiline {
1544 CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1545 : CommandObjectParsed(interpreter, "command script add",
1546 "Add a scripted function as an LLDB command.",
1548 IOHandlerDelegateMultiline("DONE"), m_options() {
1549 CommandArgumentEntry arg1;
1550 CommandArgumentData cmd_arg;
1552 // Define the first (and only) variant of this arg.
1553 cmd_arg.arg_type = eArgTypeCommandName;
1554 cmd_arg.arg_repetition = eArgRepeatPlain;
1556 // There is only one variant this argument could be; put it into the
1558 arg1.push_back(cmd_arg);
1560 // Push the data for the first argument into the m_arguments vector.
1561 m_arguments.push_back(arg1);
1564 ~CommandObjectCommandsScriptAdd() override = default;
1566 Options *GetOptions() override { return &m_options; }
1569 class CommandOptions : public Options {
1572 : Options(), m_class_name(), m_funct_name(), m_short_help(),
1573 m_synchronicity(eScriptedCommandSynchronicitySynchronous) {}
1575 ~CommandOptions() override = default;
1577 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1578 ExecutionContext *execution_context) override {
1580 const int short_option = m_getopt_table[option_idx].val;
1582 switch (short_option) {
1584 if (!option_arg.empty())
1585 m_funct_name = option_arg;
1588 if (!option_arg.empty())
1589 m_class_name = option_arg;
1592 if (!option_arg.empty())
1593 m_short_help = option_arg;
1597 (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum(
1598 option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
1599 if (!error.Success())
1600 error.SetErrorStringWithFormat(
1601 "unrecognized value for synchronicity '%s'",
1602 option_arg.str().c_str());
1605 error.SetErrorStringWithFormat("unrecognized option '%c'",
1613 void OptionParsingStarting(ExecutionContext *execution_context) override {
1614 m_class_name.clear();
1615 m_funct_name.clear();
1616 m_short_help.clear();
1617 m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1620 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1621 return llvm::makeArrayRef(g_script_add_options);
1624 // Instance variables to hold the values for command options.
1626 std::string m_class_name;
1627 std::string m_funct_name;
1628 std::string m_short_help;
1629 ScriptedCommandSynchronicity m_synchronicity;
1632 void IOHandlerActivated(IOHandler &io_handler) override {
1633 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1635 output_sp->PutCString(g_python_command_instructions);
1640 void IOHandlerInputComplete(IOHandler &io_handler,
1641 std::string &data) override {
1642 StreamFileSP error_sp = io_handler.GetErrorStreamFile();
1644 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1648 lines.SplitIntoLines(data);
1649 if (lines.GetSize() > 0) {
1650 std::string funct_name_str;
1651 if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1652 if (funct_name_str.empty()) {
1653 error_sp->Printf("error: unable to obtain a function name, didn't "
1654 "add python command.\n");
1657 // everything should be fine now, let's add this alias
1659 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
1660 m_interpreter, m_cmd_name, funct_name_str, m_short_help,
1663 if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp,
1665 error_sp->Printf("error: unable to add selected command, didn't "
1666 "add python command.\n");
1672 "error: unable to create function, didn't add python command.\n");
1676 error_sp->Printf("error: empty function, didn't add python command.\n");
1681 "error: script interpreter missing, didn't add python command.\n");
1685 io_handler.SetIsDone(true);
1689 bool DoExecute(Args &command, CommandReturnObject &result) override {
1690 if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1691 lldb::eScriptLanguagePython) {
1692 result.AppendError("only scripting language supported for scripted "
1693 "commands is currently Python");
1694 result.SetStatus(eReturnStatusFailed);
1698 if (command.GetArgumentCount() != 1) {
1699 result.AppendError("'command script add' requires one argument");
1700 result.SetStatus(eReturnStatusFailed);
1704 // Store the options in case we get multi-line input
1705 m_cmd_name = command[0].ref;
1706 m_short_help.assign(m_options.m_short_help);
1707 m_synchronicity = m_options.m_synchronicity;
1709 if (m_options.m_class_name.empty()) {
1710 if (m_options.m_funct_name.empty()) {
1711 m_interpreter.GetPythonCommandsFromIOHandler(
1713 *this, // IOHandlerDelegate
1714 true, // Run IOHandler in async mode
1715 nullptr); // Baton for the "io_handler" that will be passed back
1716 // into our IOHandlerDelegate functions
1718 CommandObjectSP new_cmd(new CommandObjectPythonFunction(
1719 m_interpreter, m_cmd_name, m_options.m_funct_name,
1720 m_options.m_short_help, m_synchronicity));
1721 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1722 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1724 result.AppendError("cannot add command");
1725 result.SetStatus(eReturnStatusFailed);
1729 ScriptInterpreter *interpreter =
1730 GetCommandInterpreter().GetScriptInterpreter();
1732 result.AppendError("cannot find ScriptInterpreter");
1733 result.SetStatus(eReturnStatusFailed);
1737 auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1738 m_options.m_class_name.c_str());
1740 result.AppendError("cannot create helper object");
1741 result.SetStatus(eReturnStatusFailed);
1745 CommandObjectSP new_cmd(new CommandObjectScriptingObject(
1746 m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1747 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1748 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1750 result.AppendError("cannot add command");
1751 result.SetStatus(eReturnStatusFailed);
1755 return result.Succeeded();
1758 CommandOptions m_options;
1759 std::string m_cmd_name;
1760 std::string m_short_help;
1761 ScriptedCommandSynchronicity m_synchronicity;
1764 //-------------------------------------------------------------------------
1765 // CommandObjectCommandsScriptList
1766 //-------------------------------------------------------------------------
1768 class CommandObjectCommandsScriptList : public CommandObjectParsed {
1770 CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1771 : CommandObjectParsed(interpreter, "command script list",
1772 "List defined scripted commands.", nullptr) {}
1774 ~CommandObjectCommandsScriptList() override = default;
1776 bool DoExecute(Args &command, CommandReturnObject &result) override {
1777 m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1779 result.SetStatus(eReturnStatusSuccessFinishResult);
1785 //-------------------------------------------------------------------------
1786 // CommandObjectCommandsScriptClear
1787 //-------------------------------------------------------------------------
1789 class CommandObjectCommandsScriptClear : public CommandObjectParsed {
1791 CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1792 : CommandObjectParsed(interpreter, "command script clear",
1793 "Delete all scripted commands.", nullptr) {}
1795 ~CommandObjectCommandsScriptClear() override = default;
1798 bool DoExecute(Args &command, CommandReturnObject &result) override {
1799 m_interpreter.RemoveAllUser();
1801 result.SetStatus(eReturnStatusSuccessFinishResult);
1807 //-------------------------------------------------------------------------
1808 // CommandObjectCommandsScriptDelete
1809 //-------------------------------------------------------------------------
1811 class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
1813 CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1814 : CommandObjectParsed(interpreter, "command script delete",
1815 "Delete a scripted command.", nullptr) {
1816 CommandArgumentEntry arg1;
1817 CommandArgumentData cmd_arg;
1819 // Define the first (and only) variant of this arg.
1820 cmd_arg.arg_type = eArgTypeCommandName;
1821 cmd_arg.arg_repetition = eArgRepeatPlain;
1823 // There is only one variant this argument could be; put it into the
1825 arg1.push_back(cmd_arg);
1827 // Push the data for the first argument into the m_arguments vector.
1828 m_arguments.push_back(arg1);
1831 ~CommandObjectCommandsScriptDelete() override = default;
1834 bool DoExecute(Args &command, CommandReturnObject &result) override {
1836 if (command.GetArgumentCount() != 1) {
1837 result.AppendError("'command script delete' requires one argument");
1838 result.SetStatus(eReturnStatusFailed);
1842 auto cmd_name = command[0].ref;
1844 if (cmd_name.empty() || !m_interpreter.HasUserCommands() ||
1845 !m_interpreter.UserCommandExists(cmd_name)) {
1846 result.AppendErrorWithFormat("command %s not found", command[0].c_str());
1847 result.SetStatus(eReturnStatusFailed);
1851 m_interpreter.RemoveUser(cmd_name);
1852 result.SetStatus(eReturnStatusSuccessFinishResult);
1857 #pragma mark CommandObjectMultiwordCommandsScript
1859 //-------------------------------------------------------------------------
1860 // CommandObjectMultiwordCommandsScript
1861 //-------------------------------------------------------------------------
1863 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
1865 CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1866 : CommandObjectMultiword(
1867 interpreter, "command script", "Commands for managing custom "
1868 "commands implemented by "
1869 "interpreter scripts.",
1870 "command script <subcommand> [<subcommand-options>]") {
1871 LoadSubCommand("add", CommandObjectSP(
1872 new CommandObjectCommandsScriptAdd(interpreter)));
1875 CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1878 CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1879 LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1883 CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1886 ~CommandObjectMultiwordCommandsScript() override = default;
1889 #pragma mark CommandObjectMultiwordCommands
1891 //-------------------------------------------------------------------------
1892 // CommandObjectMultiwordCommands
1893 //-------------------------------------------------------------------------
1895 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
1896 CommandInterpreter &interpreter)
1897 : CommandObjectMultiword(interpreter, "command",
1898 "Commands for managing custom LLDB commands.",
1899 "command <subcommand> [<subcommand-options>]") {
1900 LoadSubCommand("source",
1901 CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
1902 LoadSubCommand("alias",
1903 CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
1904 LoadSubCommand("unalias", CommandObjectSP(
1905 new CommandObjectCommandsUnalias(interpreter)));
1906 LoadSubCommand("delete",
1907 CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
1909 "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
1910 LoadSubCommand("history", CommandObjectSP(
1911 new CommandObjectCommandsHistory(interpreter)));
1914 CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
1917 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;