1 //===-- CommandObjectCommands.cpp -----------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "CommandObjectCommands.h"
10 #include "CommandObjectHelp.h"
11 #include "CommandObjectRegexCommand.h"
12 #include "lldb/Core/Debugger.h"
13 #include "lldb/Core/IOHandler.h"
14 #include "lldb/Interpreter/CommandHistory.h"
15 #include "lldb/Interpreter/CommandInterpreter.h"
16 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
17 #include "lldb/Interpreter/CommandReturnObject.h"
18 #include "lldb/Interpreter/OptionArgParser.h"
19 #include "lldb/Interpreter/OptionValueBoolean.h"
20 #include "lldb/Interpreter/OptionValueString.h"
21 #include "lldb/Interpreter/OptionValueUInt64.h"
22 #include "lldb/Interpreter/Options.h"
23 #include "lldb/Interpreter/ScriptInterpreter.h"
24 #include "lldb/Utility/Args.h"
25 #include "lldb/Utility/StringList.h"
26 #include "llvm/ADT/StringRef.h"
30 using namespace lldb_private
;
32 // CommandObjectCommandsSource
34 #define LLDB_OPTIONS_source
35 #include "CommandOptions.inc"
37 class CommandObjectCommandsSource
: public CommandObjectParsed
{
39 CommandObjectCommandsSource(CommandInterpreter
&interpreter
)
40 : CommandObjectParsed(
41 interpreter
, "command source",
42 "Read and execute LLDB commands from the file <filename>.",
44 AddSimpleArgumentList(eArgTypeFilename
);
47 ~CommandObjectCommandsSource() override
= default;
49 std::optional
<std::string
> GetRepeatCommand(Args
¤t_command_args
,
50 uint32_t index
) override
{
51 return std::string("");
54 Options
*GetOptions() override
{ return &m_options
; }
57 class CommandOptions
: public Options
{
60 : m_stop_on_error(true), m_silent_run(false), m_stop_on_continue(true),
61 m_cmd_relative_to_command_file(false) {}
63 ~CommandOptions() override
= default;
65 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
66 ExecutionContext
*execution_context
) override
{
68 const int short_option
= m_getopt_table
[option_idx
].val
;
70 switch (short_option
) {
72 error
= m_stop_on_error
.SetValueFromString(option_arg
);
76 error
= m_stop_on_continue
.SetValueFromString(option_arg
);
80 m_cmd_relative_to_command_file
= true;
84 error
= m_silent_run
.SetValueFromString(option_arg
);
88 llvm_unreachable("Unimplemented option");
94 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
95 m_stop_on_error
.Clear();
97 m_stop_on_continue
.Clear();
98 m_cmd_relative_to_command_file
.Clear();
101 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
102 return llvm::ArrayRef(g_source_options
);
105 // Instance variables to hold the values for command options.
107 OptionValueBoolean m_stop_on_error
;
108 OptionValueBoolean m_silent_run
;
109 OptionValueBoolean m_stop_on_continue
;
110 OptionValueBoolean m_cmd_relative_to_command_file
;
113 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
114 if (command
.GetArgumentCount() != 1) {
115 result
.AppendErrorWithFormat(
116 "'%s' takes exactly one executable filename argument.\n",
117 GetCommandName().str().c_str());
121 FileSpec source_dir
= {};
122 if (m_options
.m_cmd_relative_to_command_file
) {
123 source_dir
= GetDebugger().GetCommandInterpreter().GetCurrentSourceDir();
125 result
.AppendError("command source -C can only be specified "
126 "from a command file");
127 result
.SetStatus(eReturnStatusFailed
);
132 FileSpec
cmd_file(command
[0].ref());
134 // Prepend the source_dir to the cmd_file path:
135 if (!cmd_file
.IsRelative()) {
136 result
.AppendError("command source -C can only be used "
137 "with a relative path.");
138 result
.SetStatus(eReturnStatusFailed
);
141 cmd_file
.MakeAbsolute(source_dir
);
144 FileSystem::Instance().Resolve(cmd_file
);
146 CommandInterpreterRunOptions options
;
147 // If any options were set, then use them
148 if (m_options
.m_stop_on_error
.OptionWasSet() ||
149 m_options
.m_silent_run
.OptionWasSet() ||
150 m_options
.m_stop_on_continue
.OptionWasSet()) {
151 if (m_options
.m_stop_on_continue
.OptionWasSet())
152 options
.SetStopOnContinue(
153 m_options
.m_stop_on_continue
.GetCurrentValue());
155 if (m_options
.m_stop_on_error
.OptionWasSet())
156 options
.SetStopOnError(m_options
.m_stop_on_error
.GetCurrentValue());
158 // Individual silent setting is override for global command echo settings.
159 if (m_options
.m_silent_run
.GetCurrentValue()) {
160 options
.SetSilent(true);
162 options
.SetPrintResults(true);
163 options
.SetPrintErrors(true);
164 options
.SetEchoCommands(m_interpreter
.GetEchoCommands());
165 options
.SetEchoCommentCommands(m_interpreter
.GetEchoCommentCommands());
169 m_interpreter
.HandleCommandsFromFile(cmd_file
, options
, result
);
172 CommandOptions m_options
;
175 #pragma mark CommandObjectCommandsAlias
176 // CommandObjectCommandsAlias
178 #define LLDB_OPTIONS_alias
179 #include "CommandOptions.inc"
181 static const char *g_python_command_instructions
=
182 "Enter your Python command(s). Type 'DONE' to end.\n"
183 "You must define a Python function with this signature:\n"
184 "def my_command_impl(debugger, args, exe_ctx, result, internal_dict):\n";
186 class CommandObjectCommandsAlias
: public CommandObjectRaw
{
188 class CommandOptions
: public OptionGroup
{
190 CommandOptions() = default;
192 ~CommandOptions() override
= default;
194 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
195 return llvm::ArrayRef(g_alias_options
);
198 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_value
,
199 ExecutionContext
*execution_context
) override
{
202 const int short_option
= GetDefinitions()[option_idx
].short_option
;
203 std::string
option_str(option_value
);
205 switch (short_option
) {
207 m_help
.SetCurrentValue(option_str
);
208 m_help
.SetOptionWasSet();
212 m_long_help
.SetCurrentValue(option_str
);
213 m_long_help
.SetOptionWasSet();
217 llvm_unreachable("Unimplemented option");
223 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
228 OptionValueString m_help
;
229 OptionValueString m_long_help
;
232 OptionGroupOptions m_option_group
;
233 CommandOptions m_command_options
;
236 Options
*GetOptions() override
{ return &m_option_group
; }
238 CommandObjectCommandsAlias(CommandInterpreter
&interpreter
)
240 interpreter
, "command alias",
241 "Define a custom command in terms of an existing command.") {
242 m_option_group
.Append(&m_command_options
);
243 m_option_group
.Finalize();
246 "'alias' allows the user to create a short-cut or abbreviation for long \
247 commands, multi-word commands, and commands that take particular options. \
248 Below are some simple examples of how one might use the 'alias' command:"
251 (lldb) command alias sc script
253 Creates the abbreviation 'sc' for the 'script' command.
255 (lldb) command alias bp breakpoint
258 " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \
259 breakpoint commands are two-word commands, the user would still need to \
260 enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
263 (lldb) command alias bpl breakpoint list
265 Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
268 "An alias can include some options for the command, with the values either \
269 filled in at the time the alias is created, or specified as positional \
270 arguments, to be filled in when the alias is invoked. The following example \
271 shows how to create aliases with options:"
274 (lldb) command alias bfl breakpoint set -f %1 -l %2
277 " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
278 options already part of the alias. So if the user wants to set a breakpoint \
279 by file and line without explicitly having to use the -f and -l options, the \
280 user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \
281 for the actual arguments that will be passed when the alias command is used. \
282 The number in the placeholder refers to the position/order the actual value \
283 occupies when the alias is used. All the occurrences of '%1' in the alias \
284 will be replaced with the first argument, all the occurrences of '%2' in the \
285 alias will be replaced with the second argument, and so on. This also allows \
286 actual arguments to be used multiple times within an alias (see 'process \
287 launch' example below)."
291 "Note: the positional arguments must substitute as whole words in the resultant \
292 command, so you can't at present do something like this to append the file extension \
296 (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
299 "For more complex aliasing, use the \"command regex\" command instead. In the \
300 'bfl' case above, the actual file value will be filled in with the first argument \
301 following 'bfl' and the actual line number value will be filled in with the second \
302 argument. The user would use this alias as follows:"
305 (lldb) command alias bfl breakpoint set -f %1 -l %2
306 (lldb) bfl my-file.c 137
308 This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
312 (lldb) command alias pltty process launch -s -o %1 -e %1
313 (lldb) pltty /dev/tty0
315 Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
318 "If the user always wanted to pass the same value to a particular option, the \
319 alias could be defined with that value directly in the alias as a constant, \
320 rather than using a positional placeholder:"
323 (lldb) command alias bl3 breakpoint set -f %1 -l 3
325 Always sets a breakpoint on line 3 of whatever file is indicated.
329 "If the alias abbreviation or the full alias command collides with another \
330 existing command, the command resolver will prefer to use the alias over any \
331 other command as far as there is only one alias command match.");
333 CommandArgumentEntry arg1
;
334 CommandArgumentEntry arg2
;
335 CommandArgumentEntry arg3
;
336 CommandArgumentData alias_arg
;
337 CommandArgumentData cmd_arg
;
338 CommandArgumentData options_arg
;
340 // Define the first (and only) variant of this arg.
341 alias_arg
.arg_type
= eArgTypeAliasName
;
342 alias_arg
.arg_repetition
= eArgRepeatPlain
;
344 // There is only one variant this argument could be; put it into the
346 arg1
.push_back(alias_arg
);
348 // Define the first (and only) variant of this arg.
349 cmd_arg
.arg_type
= eArgTypeCommandName
;
350 cmd_arg
.arg_repetition
= eArgRepeatPlain
;
352 // There is only one variant this argument could be; put it into the
354 arg2
.push_back(cmd_arg
);
356 // Define the first (and only) variant of this arg.
357 options_arg
.arg_type
= eArgTypeAliasOptions
;
358 options_arg
.arg_repetition
= eArgRepeatOptional
;
360 // There is only one variant this argument could be; put it into the
362 arg3
.push_back(options_arg
);
364 // Push the data for the first argument into the m_arguments vector.
365 m_arguments
.push_back(arg1
);
366 m_arguments
.push_back(arg2
);
367 m_arguments
.push_back(arg3
);
370 ~CommandObjectCommandsAlias() override
= default;
373 void DoExecute(llvm::StringRef raw_command_line
,
374 CommandReturnObject
&result
) override
{
375 if (raw_command_line
.empty()) {
376 result
.AppendError("'command alias' requires at least two arguments");
380 ExecutionContext exe_ctx
= GetCommandInterpreter().GetExecutionContext();
381 m_option_group
.NotifyOptionParsingStarting(&exe_ctx
);
383 OptionsWithRaw
args_with_suffix(raw_command_line
);
385 if (args_with_suffix
.HasArgs())
386 if (!ParseOptionsAndNotify(args_with_suffix
.GetArgs(), result
,
387 m_option_group
, exe_ctx
))
390 llvm::StringRef raw_command_string
= args_with_suffix
.GetRawPart();
391 Args
args(raw_command_string
);
393 if (args
.GetArgumentCount() < 2) {
394 result
.AppendError("'command alias' requires at least two arguments");
398 // Get the alias command.
400 auto alias_command
= args
[0].ref();
401 if (alias_command
.starts_with("-")) {
402 result
.AppendError("aliases starting with a dash are not supported");
403 if (alias_command
== "--help" || alias_command
== "--long-help") {
404 result
.AppendWarning("if trying to pass options to 'command alias' add "
405 "a -- at the end of the options");
410 // Strip the new alias name off 'raw_command_string' (leave it on args,
411 // which gets passed to 'Execute', which does the stripping itself.
412 size_t pos
= raw_command_string
.find(alias_command
);
414 raw_command_string
= raw_command_string
.substr(alias_command
.size());
415 pos
= raw_command_string
.find_first_not_of(' ');
416 if ((pos
!= std::string::npos
) && (pos
> 0))
417 raw_command_string
= raw_command_string
.substr(pos
);
419 result
.AppendError("Error parsing command string. No alias created.");
423 // Verify that the command is alias-able.
424 if (m_interpreter
.CommandExists(alias_command
)) {
425 result
.AppendErrorWithFormat(
426 "'%s' is a permanent debugger command and cannot be redefined.\n",
431 if (m_interpreter
.UserMultiwordCommandExists(alias_command
)) {
432 result
.AppendErrorWithFormat(
433 "'%s' is a user container command and cannot be overwritten.\n"
434 "Delete it first with 'command container delete'\n",
439 // Get CommandObject that is being aliased. The command name is read from
440 // the front of raw_command_string. raw_command_string is returned with the
441 // name of the command object stripped off the front.
442 llvm::StringRef original_raw_command_string
= raw_command_string
;
443 CommandObject
*cmd_obj
=
444 m_interpreter
.GetCommandObjectForCommand(raw_command_string
);
447 result
.AppendErrorWithFormat("invalid command given to 'command alias'. "
448 "'%s' does not begin with a valid command."
449 " No alias created.",
450 original_raw_command_string
.str().c_str());
451 } else if (!cmd_obj
->WantsRawCommandString()) {
452 // Note that args was initialized with the original command, and has not
453 // been updated to this point. Therefore can we pass it to the version of
454 // Execute that does not need/expect raw input in the alias.
455 HandleAliasingNormalCommand(args
, result
);
457 HandleAliasingRawCommand(alias_command
, raw_command_string
, *cmd_obj
,
462 bool HandleAliasingRawCommand(llvm::StringRef alias_command
,
463 llvm::StringRef raw_command_string
,
464 CommandObject
&cmd_obj
,
465 CommandReturnObject
&result
) {
466 // Verify & handle any options/arguments passed to the alias command
468 OptionArgVectorSP option_arg_vector_sp
=
469 OptionArgVectorSP(new OptionArgVector
);
471 const bool include_aliases
= true;
472 // Look up the command using command's name first. This is to resolve
473 // aliases when you are making nested aliases. But if you don't find
474 // it that way, then it wasn't an alias and we can just use the object
475 // we were passed in.
476 CommandObjectSP cmd_obj_sp
= m_interpreter
.GetCommandSPExact(
477 cmd_obj
.GetCommandName(), include_aliases
);
479 cmd_obj_sp
= cmd_obj
.shared_from_this();
481 if (m_interpreter
.AliasExists(alias_command
) ||
482 m_interpreter
.UserCommandExists(alias_command
)) {
483 result
.AppendWarningWithFormat(
484 "Overwriting existing definition for '%s'.\n",
485 alias_command
.str().c_str());
487 if (CommandAlias
*alias
= m_interpreter
.AddAlias(
488 alias_command
, cmd_obj_sp
, raw_command_string
)) {
489 if (m_command_options
.m_help
.OptionWasSet())
490 alias
->SetHelp(m_command_options
.m_help
.GetCurrentValue());
491 if (m_command_options
.m_long_help
.OptionWasSet())
492 alias
->SetHelpLong(m_command_options
.m_long_help
.GetCurrentValue());
493 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
495 result
.AppendError("Unable to create requested alias.\n");
497 return result
.Succeeded();
500 bool HandleAliasingNormalCommand(Args
&args
, CommandReturnObject
&result
) {
501 size_t argc
= args
.GetArgumentCount();
504 result
.AppendError("'command alias' requires at least two arguments");
508 // Save these in std::strings since we're going to shift them off.
509 const std::string
alias_command(std::string(args
[0].ref()));
510 const std::string
actual_command(std::string(args
[1].ref()));
512 args
.Shift(); // Shift the alias command word off the argument vector.
513 args
.Shift(); // Shift the old command word off the argument vector.
515 // Verify that the command is alias'able, and get the appropriate command
518 if (m_interpreter
.CommandExists(alias_command
)) {
519 result
.AppendErrorWithFormat(
520 "'%s' is a permanent debugger command and cannot be redefined.\n",
521 alias_command
.c_str());
525 if (m_interpreter
.UserMultiwordCommandExists(alias_command
)) {
526 result
.AppendErrorWithFormat(
527 "'%s' is user container command and cannot be overwritten.\n"
528 "Delete it first with 'command container delete'",
529 alias_command
.c_str());
533 CommandObjectSP
command_obj_sp(
534 m_interpreter
.GetCommandSPExact(actual_command
, true));
535 CommandObjectSP subcommand_obj_sp
;
536 bool use_subcommand
= false;
537 if (!command_obj_sp
) {
538 result
.AppendErrorWithFormat("'%s' is not an existing command.\n",
539 actual_command
.c_str());
542 CommandObject
*cmd_obj
= command_obj_sp
.get();
543 CommandObject
*sub_cmd_obj
= nullptr;
544 OptionArgVectorSP option_arg_vector_sp
=
545 OptionArgVectorSP(new OptionArgVector
);
547 while (cmd_obj
->IsMultiwordObject() && !args
.empty()) {
548 auto sub_command
= args
[0].ref();
549 assert(!sub_command
.empty());
550 subcommand_obj_sp
= cmd_obj
->GetSubcommandSP(sub_command
);
551 if (!subcommand_obj_sp
) {
552 result
.AppendErrorWithFormat(
553 "'%s' is not a valid sub-command of '%s'. "
554 "Unable to create alias.\n",
555 args
[0].c_str(), actual_command
.c_str());
559 sub_cmd_obj
= subcommand_obj_sp
.get();
560 use_subcommand
= true;
561 args
.Shift(); // Shift the sub_command word off the argument vector.
562 cmd_obj
= sub_cmd_obj
;
565 // Verify & handle any options/arguments passed to the alias command
567 std::string args_string
;
570 CommandObjectSP tmp_sp
=
571 m_interpreter
.GetCommandSPExact(cmd_obj
->GetCommandName());
573 tmp_sp
= m_interpreter
.GetCommandSPExact(sub_cmd_obj
->GetCommandName());
575 args
.GetCommandString(args_string
);
578 if (m_interpreter
.AliasExists(alias_command
) ||
579 m_interpreter
.UserCommandExists(alias_command
)) {
580 result
.AppendWarningWithFormat(
581 "Overwriting existing definition for '%s'.\n", alias_command
.c_str());
584 if (CommandAlias
*alias
= m_interpreter
.AddAlias(
585 alias_command
, use_subcommand
? subcommand_obj_sp
: command_obj_sp
,
587 if (m_command_options
.m_help
.OptionWasSet())
588 alias
->SetHelp(m_command_options
.m_help
.GetCurrentValue());
589 if (m_command_options
.m_long_help
.OptionWasSet())
590 alias
->SetHelpLong(m_command_options
.m_long_help
.GetCurrentValue());
591 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
593 result
.AppendError("Unable to create requested alias.\n");
597 return result
.Succeeded();
601 #pragma mark CommandObjectCommandsUnalias
602 // CommandObjectCommandsUnalias
604 class CommandObjectCommandsUnalias
: public CommandObjectParsed
{
606 CommandObjectCommandsUnalias(CommandInterpreter
&interpreter
)
607 : CommandObjectParsed(
608 interpreter
, "command unalias",
609 "Delete one or more custom commands defined by 'command alias'.",
611 AddSimpleArgumentList(eArgTypeAliasName
);
614 ~CommandObjectCommandsUnalias() override
= default;
617 HandleArgumentCompletion(CompletionRequest
&request
,
618 OptionElementVector
&opt_element_vector
) override
{
619 if (!m_interpreter
.HasCommands() || request
.GetCursorIndex() != 0)
622 for (const auto &ent
: m_interpreter
.GetAliases()) {
623 request
.TryCompleteCurrentArg(ent
.first
, ent
.second
->GetHelp());
628 void DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
629 CommandObject::CommandMap::iterator pos
;
630 CommandObject
*cmd_obj
;
633 result
.AppendError("must call 'unalias' with a valid alias");
637 auto command_name
= args
[0].ref();
638 cmd_obj
= m_interpreter
.GetCommandObject(command_name
);
640 result
.AppendErrorWithFormat(
641 "'%s' is not a known command.\nTry 'help' to see a "
642 "current list of commands.\n",
647 if (m_interpreter
.CommandExists(command_name
)) {
648 if (cmd_obj
->IsRemovable()) {
649 result
.AppendErrorWithFormat(
650 "'%s' is not an alias, it is a debugger command which can be "
651 "removed using the 'command delete' command.\n",
654 result
.AppendErrorWithFormat(
655 "'%s' is a permanent debugger command and cannot be removed.\n",
661 if (!m_interpreter
.RemoveAlias(command_name
)) {
662 if (m_interpreter
.AliasExists(command_name
))
663 result
.AppendErrorWithFormat(
664 "Error occurred while attempting to unalias '%s'.\n",
667 result
.AppendErrorWithFormat("'%s' is not an existing alias.\n",
672 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
676 #pragma mark CommandObjectCommandsDelete
677 // CommandObjectCommandsDelete
679 class CommandObjectCommandsDelete
: public CommandObjectParsed
{
681 CommandObjectCommandsDelete(CommandInterpreter
&interpreter
)
682 : CommandObjectParsed(
683 interpreter
, "command delete",
684 "Delete one or more custom commands defined by 'command regex'.",
686 AddSimpleArgumentList(eArgTypeCommandName
);
689 ~CommandObjectCommandsDelete() override
= default;
692 HandleArgumentCompletion(CompletionRequest
&request
,
693 OptionElementVector
&opt_element_vector
) override
{
694 if (!m_interpreter
.HasCommands() || request
.GetCursorIndex() != 0)
697 for (const auto &ent
: m_interpreter
.GetCommands()) {
698 if (ent
.second
->IsRemovable())
699 request
.TryCompleteCurrentArg(ent
.first
, ent
.second
->GetHelp());
704 void DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
705 CommandObject::CommandMap::iterator pos
;
708 result
.AppendErrorWithFormat("must call '%s' with one or more valid user "
709 "defined regular expression command names",
710 GetCommandName().str().c_str());
714 auto command_name
= args
[0].ref();
715 if (!m_interpreter
.CommandExists(command_name
)) {
716 StreamString error_msg_stream
;
717 const bool generate_upropos
= true;
718 const bool generate_type_lookup
= false;
719 CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
720 &error_msg_stream
, command_name
, llvm::StringRef(), llvm::StringRef(),
721 generate_upropos
, generate_type_lookup
);
722 result
.AppendError(error_msg_stream
.GetString());
726 if (!m_interpreter
.RemoveCommand(command_name
)) {
727 result
.AppendErrorWithFormat(
728 "'%s' is a permanent debugger command and cannot be removed.\n",
733 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
737 // CommandObjectCommandsAddRegex
739 #define LLDB_OPTIONS_regex
740 #include "CommandOptions.inc"
742 #pragma mark CommandObjectCommandsAddRegex
744 class CommandObjectCommandsAddRegex
: public CommandObjectParsed
,
745 public IOHandlerDelegateMultiline
{
747 CommandObjectCommandsAddRegex(CommandInterpreter
&interpreter
)
748 : CommandObjectParsed(
749 interpreter
, "command regex",
750 "Define a custom command in terms of "
751 "existing commands by matching "
752 "regular expressions.",
753 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
754 IOHandlerDelegateMultiline("",
755 IOHandlerDelegate::Completion::LLDBCommand
) {
759 "This command allows the user to create powerful regular expression commands \
760 with substitutions. The regular expressions and substitutions are specified \
761 using the regular expression substitution format of:"
767 "<regex> is a regular expression that can use parenthesis to capture regular \
768 expression input and substitute the captured matches in the output using %1 \
769 for the first match, %2 for the second, and so on."
773 "The regular expressions can all be specified on the command line if more than \
774 one argument is provided. If just the command name is provided on the command \
775 line, then the regular expressions and substitutions can be entered on separate \
776 lines, followed by an empty line to terminate the command definition."
782 "The following example will define a regular expression command named 'f' that \
783 will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
784 a number follows 'f':"
787 (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
788 AddSimpleArgumentList(eArgTypeSEDStylePair
, eArgRepeatOptional
);
791 ~CommandObjectCommandsAddRegex() override
= default;
794 void IOHandlerActivated(IOHandler
&io_handler
, bool interactive
) override
{
795 StreamFileSP
output_sp(io_handler
.GetOutputStreamFileSP());
796 if (output_sp
&& interactive
) {
797 output_sp
->PutCString("Enter one or more sed substitution commands in "
798 "the form: 's/<regex>/<subst>/'.\nTerminate the "
799 "substitution list with an empty line.\n");
804 void IOHandlerInputComplete(IOHandler
&io_handler
,
805 std::string
&data
) override
{
806 io_handler
.SetIsDone(true);
807 if (m_regex_cmd_up
) {
809 if (lines
.SplitIntoLines(data
)) {
810 bool check_only
= false;
811 for (const std::string
&line
: lines
) {
812 Status error
= AppendRegexSubstitution(line
, check_only
);
814 if (!GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) {
815 StreamSP out_stream
= GetDebugger().GetAsyncOutputStream();
816 out_stream
->Printf("error: %s\n", error
.AsCString());
821 if (m_regex_cmd_up
->HasRegexEntries()) {
822 CommandObjectSP
cmd_sp(m_regex_cmd_up
.release());
823 m_interpreter
.AddCommand(cmd_sp
->GetCommandName(), cmd_sp
, true);
828 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
829 const size_t argc
= command
.GetArgumentCount();
831 result
.AppendError("usage: 'command regex <command-name> "
832 "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
837 auto name
= command
[0].ref();
838 m_regex_cmd_up
= std::make_unique
<CommandObjectRegexCommand
>(
839 m_interpreter
, name
, m_options
.GetHelp(), m_options
.GetSyntax(), 0,
843 Debugger
&debugger
= GetDebugger();
844 bool color_prompt
= debugger
.GetUseColor();
845 const bool multiple_lines
= true; // Get multiple lines
846 IOHandlerSP
io_handler_sp(new IOHandlerEditline(
847 debugger
, IOHandler::Type::Other
,
848 "lldb-regex", // Name of input reader for history
849 llvm::StringRef("> "), // Prompt
850 llvm::StringRef(), // Continuation prompt
851 multiple_lines
, color_prompt
,
852 0, // Don't show line numbers
856 debugger
.RunIOHandlerAsync(io_handler_sp
);
857 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
860 for (auto &entry
: command
.entries().drop_front()) {
861 bool check_only
= false;
862 error
= AppendRegexSubstitution(entry
.ref(), check_only
);
867 if (error
.Success()) {
868 AddRegexCommandToInterpreter();
872 result
.AppendError(error
.AsCString());
876 Status
AppendRegexSubstitution(const llvm::StringRef
®ex_sed
,
880 if (!m_regex_cmd_up
) {
881 return Status::FromErrorStringWithFormat(
882 "invalid regular expression command object for: '%.*s'",
883 (int)regex_sed
.size(), regex_sed
.data());
887 size_t regex_sed_size
= regex_sed
.size();
889 if (regex_sed_size
<= 1) {
890 return Status::FromErrorStringWithFormat(
891 "regular expression substitution string is too short: '%.*s'",
892 (int)regex_sed
.size(), regex_sed
.data());
896 if (regex_sed
[0] != 's') {
897 return Status::FromErrorStringWithFormat(
898 "regular expression substitution string "
899 "doesn't start with 's': '%.*s'",
900 (int)regex_sed
.size(), regex_sed
.data());
903 const size_t first_separator_char_pos
= 1;
904 // use the char that follows 's' as the regex separator character so we can
905 // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
906 const char separator_char
= regex_sed
[first_separator_char_pos
];
907 const size_t second_separator_char_pos
=
908 regex_sed
.find(separator_char
, first_separator_char_pos
+ 1);
910 if (second_separator_char_pos
== std::string::npos
) {
911 return Status::FromErrorStringWithFormat(
912 "missing second '%c' separator char after '%.*s' in '%.*s'",
914 (int)(regex_sed
.size() - first_separator_char_pos
- 1),
915 regex_sed
.data() + (first_separator_char_pos
+ 1),
916 (int)regex_sed
.size(), regex_sed
.data());
920 const size_t third_separator_char_pos
=
921 regex_sed
.find(separator_char
, second_separator_char_pos
+ 1);
923 if (third_separator_char_pos
== std::string::npos
) {
924 return Status::FromErrorStringWithFormat(
925 "missing third '%c' separator char after '%.*s' in '%.*s'",
927 (int)(regex_sed
.size() - second_separator_char_pos
- 1),
928 regex_sed
.data() + (second_separator_char_pos
+ 1),
929 (int)regex_sed
.size(), regex_sed
.data());
933 if (third_separator_char_pos
!= regex_sed_size
- 1) {
934 // Make sure that everything that follows the last regex separator char
935 if (regex_sed
.find_first_not_of("\t\n\v\f\r ",
936 third_separator_char_pos
+ 1) !=
938 return Status::FromErrorStringWithFormat(
939 "extra data found after the '%.*s' regular expression substitution "
941 (int)third_separator_char_pos
+ 1, regex_sed
.data(),
942 (int)(regex_sed
.size() - third_separator_char_pos
- 1),
943 regex_sed
.data() + (third_separator_char_pos
+ 1));
946 } else if (first_separator_char_pos
+ 1 == second_separator_char_pos
) {
947 return Status::FromErrorStringWithFormat(
948 "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
949 separator_char
, separator_char
, separator_char
, (int)regex_sed
.size(),
952 } else if (second_separator_char_pos
+ 1 == third_separator_char_pos
) {
953 return Status::FromErrorStringWithFormat(
954 "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
955 separator_char
, separator_char
, separator_char
, (int)regex_sed
.size(),
961 std::string
regex(std::string(regex_sed
.substr(
962 first_separator_char_pos
+ 1,
963 second_separator_char_pos
- first_separator_char_pos
- 1)));
964 std::string
subst(std::string(regex_sed
.substr(
965 second_separator_char_pos
+ 1,
966 third_separator_char_pos
- second_separator_char_pos
- 1)));
967 m_regex_cmd_up
->AddRegexCommand(regex
, subst
);
972 void AddRegexCommandToInterpreter() {
973 if (m_regex_cmd_up
) {
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);
982 std::unique_ptr
<CommandObjectRegexCommand
> m_regex_cmd_up
;
984 class CommandOptions
: public Options
{
986 CommandOptions() = default;
988 ~CommandOptions() override
= default;
990 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
991 ExecutionContext
*execution_context
) override
{
993 const int short_option
= m_getopt_table
[option_idx
].val
;
995 switch (short_option
) {
997 m_help
.assign(std::string(option_arg
));
1000 m_syntax
.assign(std::string(option_arg
));
1003 llvm_unreachable("Unimplemented option");
1009 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1014 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1015 return llvm::ArrayRef(g_regex_options
);
1018 llvm::StringRef
GetHelp() { return m_help
; }
1020 llvm::StringRef
GetSyntax() { return m_syntax
; }
1023 // Instance variables to hold the values for command options.
1026 std::string m_syntax
;
1029 Options
*GetOptions() override
{ return &m_options
; }
1031 CommandOptions m_options
;
1034 class CommandObjectPythonFunction
: public CommandObjectRaw
{
1036 CommandObjectPythonFunction(CommandInterpreter
&interpreter
, std::string name
,
1037 std::string funct
, std::string help
,
1038 ScriptedCommandSynchronicity synch
,
1039 CompletionType completion_type
)
1040 : CommandObjectRaw(interpreter
, name
), m_function_name(funct
),
1041 m_synchro(synch
), m_completion_type(completion_type
) {
1045 StreamString stream
;
1046 stream
.Printf("For more information run 'help %s'", name
.c_str());
1047 SetHelp(stream
.GetString());
1051 ~CommandObjectPythonFunction() override
= default;
1053 bool IsRemovable() const override
{ return true; }
1055 const std::string
&GetFunctionName() { return m_function_name
; }
1057 ScriptedCommandSynchronicity
GetSynchronicity() { return m_synchro
; }
1059 llvm::StringRef
GetHelpLong() override
{
1060 if (m_fetched_help_long
)
1061 return CommandObjectRaw::GetHelpLong();
1063 ScriptInterpreter
*scripter
= GetDebugger().GetScriptInterpreter();
1065 return CommandObjectRaw::GetHelpLong();
1067 std::string docstring
;
1068 m_fetched_help_long
=
1069 scripter
->GetDocumentationForItem(m_function_name
.c_str(), docstring
);
1070 if (!docstring
.empty())
1071 SetHelpLong(docstring
);
1072 return CommandObjectRaw::GetHelpLong();
1076 HandleArgumentCompletion(CompletionRequest
&request
,
1077 OptionElementVector
&opt_element_vector
) override
{
1078 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1079 GetCommandInterpreter(), m_completion_type
, request
, nullptr);
1082 bool WantsCompletion() override
{ return true; }
1085 void DoExecute(llvm::StringRef raw_command_line
,
1086 CommandReturnObject
&result
) override
{
1087 ScriptInterpreter
*scripter
= GetDebugger().GetScriptInterpreter();
1089 m_interpreter
.IncreaseCommandUsage(*this);
1093 result
.SetStatus(eReturnStatusInvalid
);
1095 if (!scripter
|| !scripter
->RunScriptBasedCommand(
1096 m_function_name
.c_str(), raw_command_line
, m_synchro
,
1097 result
, error
, m_exe_ctx
)) {
1098 result
.AppendError(error
.AsCString());
1100 // Don't change the status if the command already set it...
1101 if (result
.GetStatus() == eReturnStatusInvalid
) {
1102 if (result
.GetOutputString().empty())
1103 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1105 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1111 std::string m_function_name
;
1112 ScriptedCommandSynchronicity m_synchro
;
1113 bool m_fetched_help_long
= false;
1114 CompletionType m_completion_type
= eNoCompletion
;
1117 /// This class implements a "raw" scripted command. lldb does no parsing of the
1118 /// command line, instead passing the line unaltered (except for backtick
1120 class CommandObjectScriptingObjectRaw
: public CommandObjectRaw
{
1122 CommandObjectScriptingObjectRaw(CommandInterpreter
&interpreter
,
1124 StructuredData::GenericSP cmd_obj_sp
,
1125 ScriptedCommandSynchronicity synch
,
1126 CompletionType completion_type
)
1127 : CommandObjectRaw(interpreter
, name
), m_cmd_obj_sp(cmd_obj_sp
),
1128 m_synchro(synch
), m_fetched_help_short(false),
1129 m_fetched_help_long(false), m_completion_type(completion_type
) {
1130 StreamString stream
;
1131 stream
.Printf("For more information run 'help %s'", name
.c_str());
1132 SetHelp(stream
.GetString());
1133 if (ScriptInterpreter
*scripter
= GetDebugger().GetScriptInterpreter())
1134 GetFlags().Set(scripter
->GetFlagsForCommandObject(cmd_obj_sp
));
1137 ~CommandObjectScriptingObjectRaw() override
= default;
1140 HandleArgumentCompletion(CompletionRequest
&request
,
1141 OptionElementVector
&opt_element_vector
) override
{
1142 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1143 GetCommandInterpreter(), m_completion_type
, request
, nullptr);
1146 bool WantsCompletion() override
{ return true; }
1148 bool IsRemovable() const override
{ return true; }
1150 ScriptedCommandSynchronicity
GetSynchronicity() { return m_synchro
; }
1152 std::optional
<std::string
> GetRepeatCommand(Args
&args
,
1153 uint32_t index
) override
{
1154 ScriptInterpreter
*scripter
= GetDebugger().GetScriptInterpreter();
1156 return std::nullopt
;
1158 return scripter
->GetRepeatCommandForScriptedCommand(m_cmd_obj_sp
, args
);
1161 llvm::StringRef
GetHelp() override
{
1162 if (m_fetched_help_short
)
1163 return CommandObjectRaw::GetHelp();
1164 ScriptInterpreter
*scripter
= GetDebugger().GetScriptInterpreter();
1166 return CommandObjectRaw::GetHelp();
1167 std::string docstring
;
1168 m_fetched_help_short
=
1169 scripter
->GetShortHelpForCommandObject(m_cmd_obj_sp
, docstring
);
1170 if (!docstring
.empty())
1173 return CommandObjectRaw::GetHelp();
1176 llvm::StringRef
GetHelpLong() override
{
1177 if (m_fetched_help_long
)
1178 return CommandObjectRaw::GetHelpLong();
1180 ScriptInterpreter
*scripter
= GetDebugger().GetScriptInterpreter();
1182 return CommandObjectRaw::GetHelpLong();
1184 std::string docstring
;
1185 m_fetched_help_long
=
1186 scripter
->GetLongHelpForCommandObject(m_cmd_obj_sp
, docstring
);
1187 if (!docstring
.empty())
1188 SetHelpLong(docstring
);
1189 return CommandObjectRaw::GetHelpLong();
1193 void DoExecute(llvm::StringRef raw_command_line
,
1194 CommandReturnObject
&result
) override
{
1195 ScriptInterpreter
*scripter
= GetDebugger().GetScriptInterpreter();
1199 result
.SetStatus(eReturnStatusInvalid
);
1202 !scripter
->RunScriptBasedCommand(m_cmd_obj_sp
, raw_command_line
,
1203 m_synchro
, result
, error
, m_exe_ctx
)) {
1204 result
.AppendError(error
.AsCString());
1206 // Don't change the status if the command already set it...
1207 if (result
.GetStatus() == eReturnStatusInvalid
) {
1208 if (result
.GetOutputString().empty())
1209 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1211 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1217 StructuredData::GenericSP m_cmd_obj_sp
;
1218 ScriptedCommandSynchronicity m_synchro
;
1219 bool m_fetched_help_short
: 1;
1220 bool m_fetched_help_long
: 1;
1221 CompletionType m_completion_type
= eNoCompletion
;
1225 /// This command implements a lldb parsed scripted command. The command
1226 /// provides a definition of the options and arguments, and a option value
1227 /// setting callback, and then the command's execution function gets passed
1228 /// just the parsed arguments.
1229 /// Note, implementing a command in Python using these base interfaces is a bit
1230 /// of a pain, but it is much easier to export this low level interface, and
1231 /// then make it nicer on the Python side, than to try to do that in a
1232 /// script language neutral way.
1233 /// So I've also added a base class in Python that provides a table-driven
1234 /// way of defining the options and arguments, which automatically fills the
1235 /// option values, making them available as properties in Python.
1237 class CommandObjectScriptingObjectParsed
: public CommandObjectParsed
{
1239 class CommandOptions
: public Options
{
1241 CommandOptions(CommandInterpreter
&interpreter
,
1242 StructuredData::GenericSP cmd_obj_sp
) : m_interpreter(interpreter
),
1243 m_cmd_obj_sp(cmd_obj_sp
) {}
1245 ~CommandOptions() override
= default;
1247 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1248 ExecutionContext
*execution_context
) override
{
1250 ScriptInterpreter
*scripter
=
1251 m_interpreter
.GetDebugger().GetScriptInterpreter();
1253 return Status::FromErrorString(
1254 "No script interpreter for SetOptionValue.");
1257 if (!m_cmd_obj_sp
) {
1258 return Status::FromErrorString(
1259 "SetOptionValue called with empty cmd_obj.");
1262 if (!m_options_definition_up
) {
1263 return Status::FromErrorString(
1264 "SetOptionValue called before options definitions "
1268 // Pass the long option, since you aren't actually required to have a
1269 // short_option, and for those options the index or short option character
1270 // aren't meaningful on the python side.
1271 const char * long_option
=
1272 m_options_definition_up
.get()[option_idx
].long_option
;
1273 bool success
= scripter
->SetOptionValueForCommandObject(m_cmd_obj_sp
,
1274 execution_context
, long_option
, option_arg
);
1276 return Status::FromErrorStringWithFormatv(
1277 "Error setting option: {0} to {1}", long_option
, option_arg
);
1281 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1282 ScriptInterpreter
*scripter
=
1283 m_interpreter
.GetDebugger().GetScriptInterpreter();
1284 if (!scripter
|| !m_cmd_obj_sp
)
1287 scripter
->OptionParsingStartedForCommandObject(m_cmd_obj_sp
);
1290 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1291 if (!m_options_definition_up
)
1293 return llvm::ArrayRef(m_options_definition_up
.get(), m_num_options
);
1296 static Status
ParseUsageMaskFromArray(StructuredData::ObjectSP obj_sp
,
1297 size_t counter
, uint32_t &usage_mask
) {
1298 // If the usage entry is not provided, we use LLDB_OPT_SET_ALL.
1299 // If the usage mask is a UINT, the option belongs to that group.
1300 // If the usage mask is a vector of UINT's, the option belongs to all the
1302 // If a subelement of the vector is a vector of two ints, then the option
1303 // belongs to the inclusive range from the first to the second element.
1306 usage_mask
= LLDB_OPT_SET_ALL
;
1312 StructuredData::UnsignedInteger
*uint_val
=
1313 obj_sp
->GetAsUnsignedInteger();
1315 // If this is an integer, then this specifies a single group:
1316 uint32_t value
= uint_val
->GetValue();
1318 return Status::FromErrorStringWithFormatv(
1319 "0 is not a valid group for option {0}", counter
);
1321 usage_mask
= (1 << (value
- 1));
1324 // Otherwise it has to be an array:
1325 StructuredData::Array
*array_val
= obj_sp
->GetAsArray();
1327 return Status::FromErrorStringWithFormatv(
1328 "required field is not a array for option {0}", counter
);
1330 // This is the array ForEach for accumulating a group usage mask from
1331 // an array of string descriptions of groups.
1332 auto groups_accumulator
1333 = [counter
, &usage_mask
, &error
]
1334 (StructuredData::Object
*obj
) -> bool {
1335 StructuredData::UnsignedInteger
*int_val
= obj
->GetAsUnsignedInteger();
1337 uint32_t value
= int_val
->GetValue();
1339 error
= Status::FromErrorStringWithFormatv(
1340 "0 is not a valid group for element {0}", counter
);
1343 usage_mask
|= (1 << (value
- 1));
1346 StructuredData::Array
*arr_val
= obj
->GetAsArray();
1348 error
= Status::FromErrorStringWithFormatv(
1349 "Group element not an int or array of integers for element {0}",
1353 size_t num_range_elem
= arr_val
->GetSize();
1354 if (num_range_elem
!= 2) {
1355 error
= Status::FromErrorStringWithFormatv(
1356 "Subranges of a group not a start and a stop for element {0}",
1360 int_val
= arr_val
->GetItemAtIndex(0)->GetAsUnsignedInteger();
1362 error
= Status::FromErrorStringWithFormatv(
1363 "Start element of a subrange of a "
1364 "group not unsigned int for element {0}",
1368 uint32_t start
= int_val
->GetValue();
1369 int_val
= arr_val
->GetItemAtIndex(1)->GetAsUnsignedInteger();
1371 error
= Status::FromErrorStringWithFormatv(
1372 "End element of a subrange of a group"
1373 " not unsigned int for element {0}",
1377 uint32_t end
= int_val
->GetValue();
1378 if (start
== 0 || end
== 0 || start
> end
) {
1379 error
= Status::FromErrorStringWithFormatv(
1380 "Invalid subrange of a group: {0} - "
1381 "{1} for element {2}",
1382 start
, end
, counter
);
1385 for (uint32_t i
= start
; i
<= end
; i
++) {
1386 usage_mask
|= (1 << (i
- 1));
1390 array_val
->ForEach(groups_accumulator
);
1395 Status
SetOptionsFromArray(StructuredData::Dictionary
&options
) {
1397 m_num_options
= options
.GetSize();
1398 m_options_definition_up
.reset(new OptionDefinition
[m_num_options
]);
1399 // We need to hand out pointers to contents of these vectors; we reserve
1400 // as much as we'll need up front so they don't get freed on resize...
1401 m_usage_container
.resize(m_num_options
);
1402 m_enum_storage
.resize(m_num_options
);
1403 m_enum_vector
.resize(m_num_options
);
1406 size_t short_opt_counter
= 0;
1407 // This is the Array::ForEach function for adding option elements:
1408 auto add_element
= [this, &error
, &counter
, &short_opt_counter
]
1409 (llvm::StringRef long_option
, StructuredData::Object
*object
) -> bool {
1410 StructuredData::Dictionary
*opt_dict
= object
->GetAsDictionary();
1412 error
= Status::FromErrorString(
1413 "Value in options dictionary is not a dictionary");
1416 OptionDefinition
&option_def
= m_options_definition_up
.get()[counter
];
1418 // We aren't exposing the validator yet, set it to null
1419 option_def
.validator
= nullptr;
1420 // We don't require usage masks, so set it to one group by default:
1421 option_def
.usage_mask
= 1;
1423 // Now set the fields of the OptionDefinition Array from the dictionary:
1425 // Note that I don't check for unknown fields in the option dictionaries
1426 // so a scriptor can add extra elements that are helpful when they go to
1427 // do "set_option_value"
1430 StructuredData::ObjectSP obj_sp
= opt_dict
->GetValueForKey("groups");
1432 error
= ParseUsageMaskFromArray(obj_sp
, counter
,
1433 option_def
.usage_mask
);
1439 option_def
.required
= false;
1440 obj_sp
= opt_dict
->GetValueForKey("required");
1442 StructuredData::Boolean
*boolean_val
= obj_sp
->GetAsBoolean();
1444 error
= Status::FromErrorStringWithFormatv(
1445 "'required' field is not a boolean "
1450 option_def
.required
= boolean_val
->GetValue();
1455 obj_sp
= opt_dict
->GetValueForKey("short_option");
1457 // The value is a string, so pull the
1458 llvm::StringRef short_str
= obj_sp
->GetStringValue();
1459 if (short_str
.empty()) {
1460 error
= Status::FromErrorStringWithFormatv(
1461 "short_option field empty for "
1465 } else if (short_str
.size() != 1) {
1466 error
= Status::FromErrorStringWithFormatv(
1467 "short_option field has extra "
1468 "characters for option {0}",
1472 short_option
= (int) short_str
[0];
1474 // If the short option is not provided, then we need a unique value
1475 // less than the lowest printable ASCII character.
1476 short_option
= short_opt_counter
++;
1478 option_def
.short_option
= short_option
;
1480 // Long Option is the key from the outer dict:
1481 if (long_option
.empty()) {
1482 error
= Status::FromErrorStringWithFormatv(
1483 "empty long_option for option {0}", counter
);
1486 auto inserted
= g_string_storer
.insert(long_option
.str());
1487 option_def
.long_option
= ((*(inserted
.first
)).data());
1490 obj_sp
= opt_dict
->GetValueForKey("value_type");
1492 StructuredData::UnsignedInteger
*uint_val
1493 = obj_sp
->GetAsUnsignedInteger();
1495 error
= Status::FromErrorStringWithFormatv(
1496 "Value type must be an unsigned "
1500 uint64_t val_type
= uint_val
->GetValue();
1501 if (val_type
>= eArgTypeLastArg
) {
1503 Status::FromErrorStringWithFormatv("Value type {0} beyond the "
1504 "CommandArgumentType bounds",
1508 option_def
.argument_type
= (CommandArgumentType
) val_type
;
1509 option_def
.option_has_arg
= true;
1511 option_def
.argument_type
= eArgTypeNone
;
1512 option_def
.option_has_arg
= false;
1516 obj_sp
= opt_dict
->GetValueForKey("completion_type");
1518 StructuredData::UnsignedInteger
*uint_val
= obj_sp
->GetAsUnsignedInteger();
1520 error
= Status::FromErrorStringWithFormatv(
1521 "Completion type must be an "
1522 "unsigned integer for option {0}",
1526 uint64_t completion_type
= uint_val
->GetValue();
1527 if (completion_type
> eCustomCompletion
) {
1528 error
= Status::FromErrorStringWithFormatv(
1529 "Completion type for option {0} "
1530 "beyond the CompletionType bounds",
1534 option_def
.completion_type
= (CommandArgumentType
) completion_type
;
1536 option_def
.completion_type
= eNoCompletion
;
1539 std::string usage_text
;
1540 obj_sp
= opt_dict
->GetValueForKey("help");
1542 error
= Status::FromErrorStringWithFormatv(
1543 "required usage missing from option "
1548 llvm::StringRef usage_stref
;
1549 usage_stref
= obj_sp
->GetStringValue();
1550 if (usage_stref
.empty()) {
1551 error
= Status::FromErrorStringWithFormatv(
1552 "empty usage text for option {0}", counter
);
1555 m_usage_container
[counter
] = usage_stref
.str().c_str();
1556 option_def
.usage_text
= m_usage_container
[counter
].data();
1560 obj_sp
= opt_dict
->GetValueForKey("enum_values");
1562 StructuredData::Array
*array
= obj_sp
->GetAsArray();
1564 error
= Status::FromErrorStringWithFormatv(
1565 "enum values must be an array for "
1570 size_t num_elem
= array
->GetSize();
1571 size_t enum_ctr
= 0;
1572 m_enum_storage
[counter
] = std::vector
<EnumValueStorage
>(num_elem
);
1573 std::vector
<EnumValueStorage
> &curr_elem
= m_enum_storage
[counter
];
1575 // This is the Array::ForEach function for adding enum elements:
1576 // Since there are only two fields to specify the enum, use a simple
1577 // two element array with value first, usage second.
1578 // counter is only used for reporting so I pass it by value here.
1579 auto add_enum
= [&enum_ctr
, &curr_elem
, counter
, &error
]
1580 (StructuredData::Object
*object
) -> bool {
1581 StructuredData::Array
*enum_arr
= object
->GetAsArray();
1583 error
= Status::FromErrorStringWithFormatv(
1584 "Enum values for option {0} not "
1589 size_t num_enum_elements
= enum_arr
->GetSize();
1590 if (num_enum_elements
!= 2) {
1591 error
= Status::FromErrorStringWithFormatv(
1592 "Wrong number of elements: {0} "
1593 "for enum {1} in option {2}",
1594 num_enum_elements
, enum_ctr
, counter
);
1598 StructuredData::ObjectSP obj_sp
= enum_arr
->GetItemAtIndex(0);
1599 llvm::StringRef val_stref
= obj_sp
->GetStringValue();
1600 std::string value_cstr_str
= val_stref
.str().c_str();
1603 obj_sp
= enum_arr
->GetItemAtIndex(1);
1605 error
= Status::FromErrorStringWithFormatv(
1606 "No usage for enum {0} in option "
1611 llvm::StringRef usage_stref
= obj_sp
->GetStringValue();
1612 std::string usage_cstr_str
= usage_stref
.str().c_str();
1613 curr_elem
[enum_ctr
] = EnumValueStorage(value_cstr_str
,
1614 usage_cstr_str
, enum_ctr
);
1618 }; // end of add_enum
1620 array
->ForEach(add_enum
);
1621 if (!error
.Success())
1623 // We have to have a vector of elements to set in the options, make
1625 for (auto &elem
: curr_elem
)
1626 m_enum_vector
[counter
].emplace_back(elem
.element
);
1628 option_def
.enum_values
= llvm::ArrayRef(m_enum_vector
[counter
]);
1632 }; // end of add_element
1634 options
.ForEach(add_element
);
1638 size_t GetNumOptions() { return m_num_options
; }
1640 void PrepareOptionsForCompletion(CompletionRequest
&request
,
1641 OptionElementVector
&option_vec
,
1642 ExecutionContext
*exe_ctx
) {
1643 // I'm not sure if we'll get into trouble doing an option parsing start
1644 // and end in this context. If so, then I'll have to directly tell the
1645 // scripter to do this.
1646 OptionParsingStarting(exe_ctx
);
1647 auto opt_defs
= GetDefinitions();
1649 // Iterate through the options we found so far, and push them into
1650 // the scripted side.
1651 for (auto option_elem
: option_vec
) {
1652 int cur_defs_index
= option_elem
.opt_defs_index
;
1653 // If we don't recognize this option we can't set it.
1654 if (cur_defs_index
== OptionArgElement::eUnrecognizedArg
||
1655 cur_defs_index
== OptionArgElement::eBareDash
||
1656 cur_defs_index
== OptionArgElement::eBareDoubleDash
)
1658 bool option_has_arg
= opt_defs
[cur_defs_index
].option_has_arg
;
1659 llvm::StringRef cur_arg_value
;
1660 if (option_has_arg
) {
1661 int cur_arg_pos
= option_elem
.opt_arg_pos
;
1662 if (cur_arg_pos
!= OptionArgElement::eUnrecognizedArg
&&
1663 cur_arg_pos
!= OptionArgElement::eBareDash
&&
1664 cur_arg_pos
!= OptionArgElement::eBareDoubleDash
) {
1666 request
.GetParsedLine().GetArgumentAtIndex(cur_arg_pos
);
1669 SetOptionValue(cur_defs_index
, cur_arg_value
, exe_ctx
);
1671 OptionParsingFinished(exe_ctx
);
1675 ProcessCompletionDict(CompletionRequest
&request
,
1676 StructuredData::DictionarySP
&completion_dict_sp
) {
1677 // We don't know how to process an empty completion dict, our callers have
1679 assert(completion_dict_sp
&& "Must have valid completion dict");
1680 // First handle the case of a single completion:
1681 llvm::StringRef completion
;
1682 // If the dictionary has one element "no-completion" then we return here
1683 if (completion_dict_sp
->GetValueForKeyAsString("no-completion",
1687 if (completion_dict_sp
->GetValueForKeyAsString("completion",
1689 llvm::StringRef mode_str
;
1690 CompletionMode mode
= CompletionMode::Normal
;
1691 if (completion_dict_sp
->GetValueForKeyAsString("mode", mode_str
)) {
1692 if (mode_str
== "complete")
1693 mode
= CompletionMode::Normal
;
1694 else if (mode_str
== "partial")
1695 mode
= CompletionMode::Partial
;
1697 // FIXME - how do I report errors here?
1701 request
.AddCompletion(completion
, "", mode
);
1704 // The completions are required, the descriptions are not:
1705 StructuredData::Array
*completions
;
1706 StructuredData::Array
*descriptions
;
1707 if (completion_dict_sp
->GetValueForKeyAsArray("values", completions
)) {
1708 completion_dict_sp
->GetValueForKeyAsArray("descriptions", descriptions
);
1709 size_t num_completions
= completions
->GetSize();
1710 for (size_t idx
= 0; idx
< num_completions
; idx
++) {
1711 auto val
= completions
->GetItemAtIndexAsString(idx
);
1713 // FIXME: How do I report this error?
1717 auto desc
= descriptions
->GetItemAtIndexAsString(idx
);
1718 request
.AddCompletion(*val
, desc
? *desc
: "");
1720 request
.AddCompletion(*val
);
1726 HandleOptionArgumentCompletion(lldb_private::CompletionRequest
&request
,
1727 OptionElementVector
&option_vec
,
1728 int opt_element_index
,
1729 CommandInterpreter
&interpreter
) override
{
1730 ScriptInterpreter
*scripter
=
1731 interpreter
.GetDebugger().GetScriptInterpreter();
1736 ExecutionContext exe_ctx
= interpreter
.GetExecutionContext();
1737 PrepareOptionsForCompletion(request
, option_vec
, &exe_ctx
);
1739 auto defs
= GetDefinitions();
1741 size_t defs_index
= option_vec
[opt_element_index
].opt_defs_index
;
1742 llvm::StringRef option_name
= defs
[defs_index
].long_option
;
1743 bool is_enum
= defs
[defs_index
].enum_values
.size() != 0;
1744 if (option_name
.empty())
1746 // If this is an enum, we don't call the custom completer, just let the
1747 // regular option completer handle that:
1748 StructuredData::DictionarySP completion_dict_sp
;
1750 completion_dict_sp
=
1751 scripter
->HandleOptionArgumentCompletionForScriptedCommand(
1752 m_cmd_obj_sp
, option_name
, request
.GetCursorCharPos());
1754 if (!completion_dict_sp
) {
1755 Options::HandleOptionArgumentCompletion(request
, option_vec
,
1756 opt_element_index
, interpreter
);
1760 ProcessCompletionDict(request
, completion_dict_sp
);
1764 struct EnumValueStorage
{
1765 EnumValueStorage() {
1766 element
.string_value
= "value not set";
1767 element
.usage
= "usage not set";
1771 EnumValueStorage(std::string in_str_val
, std::string in_usage
,
1772 size_t in_value
) : value(std::move(in_str_val
)), usage(std::move(in_usage
)) {
1773 SetElement(in_value
);
1776 EnumValueStorage(const EnumValueStorage
&in
) : value(in
.value
),
1778 SetElement(in
.element
.value
);
1781 EnumValueStorage
&operator=(const EnumValueStorage
&in
) {
1784 SetElement(in
.element
.value
);
1788 void SetElement(size_t in_value
) {
1789 element
.value
= in_value
;
1790 element
.string_value
= value
.data();
1791 element
.usage
= usage
.data();
1796 OptionEnumValueElement element
;
1798 // We have to provide char * values for the long option, usage and enum
1799 // values, that's what the option definitions hold.
1800 // The long option strings are quite likely to be reused in other added
1801 // commands, so those are stored in a global set: g_string_storer.
1802 // But the usages are much less likely to be reused, so those are stored in
1803 // a vector in the command instance. It gets resized to the correct size
1804 // and then filled with null-terminated strings in the std::string, so the
1805 // are valid C-strings that won't move around.
1806 // The enum values and descriptions are treated similarly - these aren't
1807 // all that common so it's not worth the effort to dedup them.
1808 size_t m_num_options
= 0;
1809 std::unique_ptr
<OptionDefinition
> m_options_definition_up
;
1810 std::vector
<std::vector
<EnumValueStorage
>> m_enum_storage
;
1811 std::vector
<std::vector
<OptionEnumValueElement
>> m_enum_vector
;
1812 std::vector
<std::string
> m_usage_container
;
1813 CommandInterpreter
&m_interpreter
;
1814 StructuredData::GenericSP m_cmd_obj_sp
;
1815 static std::unordered_set
<std::string
> g_string_storer
;
1819 static CommandObjectSP
Create(CommandInterpreter
&interpreter
,
1821 StructuredData::GenericSP cmd_obj_sp
,
1822 ScriptedCommandSynchronicity synch
,
1823 CommandReturnObject
&result
) {
1824 CommandObjectSP
new_cmd_sp(new CommandObjectScriptingObjectParsed(
1825 interpreter
, name
, cmd_obj_sp
, synch
));
1827 CommandObjectScriptingObjectParsed
*parsed_cmd
1828 = static_cast<CommandObjectScriptingObjectParsed
*>(new_cmd_sp
.get());
1829 // Now check all the failure modes, and report if found.
1830 Status opt_error
= parsed_cmd
->GetOptionsError();
1831 Status arg_error
= parsed_cmd
->GetArgsError();
1833 if (opt_error
.Fail())
1834 result
.AppendErrorWithFormat("failed to parse option definitions: %s",
1835 opt_error
.AsCString());
1836 if (arg_error
.Fail())
1837 result
.AppendErrorWithFormat("%sfailed to parse argument definitions: %s",
1838 opt_error
.Fail() ? ", also " : "",
1839 arg_error
.AsCString());
1841 if (!result
.Succeeded())
1847 CommandObjectScriptingObjectParsed(CommandInterpreter
&interpreter
,
1849 StructuredData::GenericSP cmd_obj_sp
,
1850 ScriptedCommandSynchronicity synch
)
1851 : CommandObjectParsed(interpreter
, name
.c_str()),
1852 m_cmd_obj_sp(cmd_obj_sp
), m_synchro(synch
),
1853 m_options(interpreter
, cmd_obj_sp
), m_fetched_help_short(false),
1854 m_fetched_help_long(false) {
1855 StreamString stream
;
1856 ScriptInterpreter
*scripter
= GetDebugger().GetScriptInterpreter();
1858 m_options_error
= Status::FromErrorString("No script interpreter");
1863 GetFlags().Set(scripter
->GetFlagsForCommandObject(cmd_obj_sp
));
1865 // Now set up the options definitions from the options:
1866 StructuredData::ObjectSP options_object_sp
1867 = scripter
->GetOptionsForCommandObject(cmd_obj_sp
);
1868 // It's okay not to have an options dict.
1869 if (options_object_sp
) {
1870 // The options come as a dictionary of dictionaries. The key of the
1871 // outer dict is the long option name (since that's required). The
1872 // value holds all the other option specification bits.
1873 StructuredData::Dictionary
*options_dict
1874 = options_object_sp
->GetAsDictionary();
1875 // but if it exists, it has to be an array.
1877 m_options_error
= m_options
.SetOptionsFromArray(*(options_dict
));
1878 // If we got an error don't bother with the arguments...
1879 if (m_options_error
.Fail())
1882 m_options_error
= Status::FromErrorString("Options array not an array");
1886 // Then fetch the args. Since the arguments can have usage masks you need
1887 // an array of arrays.
1888 StructuredData::ObjectSP args_object_sp
1889 = scripter
->GetArgumentsForCommandObject(cmd_obj_sp
);
1890 if (args_object_sp
) {
1891 StructuredData::Array
*args_array
= args_object_sp
->GetAsArray();
1894 Status::FromErrorString("Argument specification is not an array");
1899 // This is the Array::ForEach function that handles the
1900 // CommandArgumentEntry arrays one by one:
1901 auto arg_array_adder
= [this, &counter
] (StructuredData::Object
*object
)
1903 // This is the Array::ForEach function to add argument entries:
1904 CommandArgumentEntry this_entry
;
1905 size_t elem_counter
= 0;
1906 auto args_adder
= [this, counter
, &elem_counter
, &this_entry
]
1907 (StructuredData::Object
*object
) -> bool {
1908 // The arguments definition has three fields, the argument type, the
1909 // repeat and the usage mask.
1910 CommandArgumentType arg_type
= eArgTypeNone
;
1911 ArgumentRepetitionType arg_repetition
= eArgRepeatOptional
;
1912 uint32_t arg_opt_set_association
;
1914 auto report_error
= [this, elem_counter
,
1915 counter
](const char *err_txt
) -> bool {
1916 m_args_error
= Status::FromErrorStringWithFormatv(
1917 "Element {0} of arguments "
1918 "list element {1}: %s.",
1919 elem_counter
, counter
, err_txt
);
1923 StructuredData::Dictionary
*arg_dict
= object
->GetAsDictionary();
1925 report_error("is not a dictionary.");
1929 StructuredData::ObjectSP obj_sp
1930 = arg_dict
->GetValueForKey("arg_type");
1932 StructuredData::UnsignedInteger
*uint_val
1933 = obj_sp
->GetAsUnsignedInteger();
1935 report_error("value type must be an unsigned integer");
1938 uint64_t arg_type_int
= uint_val
->GetValue();
1939 if (arg_type_int
>= eArgTypeLastArg
) {
1940 report_error("value type beyond ArgumentRepetitionType bounds");
1943 arg_type
= (CommandArgumentType
) arg_type_int
;
1946 obj_sp
= arg_dict
->GetValueForKey("repeat");
1947 std::optional
<ArgumentRepetitionType
> repeat
;
1949 llvm::StringRef repeat_str
= obj_sp
->GetStringValue();
1950 if (repeat_str
.empty()) {
1951 report_error("repeat value is empty");
1954 repeat
= ArgRepetitionFromString(repeat_str
);
1956 report_error("invalid repeat value");
1959 arg_repetition
= *repeat
;
1963 obj_sp
= arg_dict
->GetValueForKey("groups");
1964 m_args_error
= CommandOptions::ParseUsageMaskFromArray(obj_sp
,
1965 counter
, arg_opt_set_association
);
1966 this_entry
.emplace_back(arg_type
, arg_repetition
,
1967 arg_opt_set_association
);
1971 StructuredData::Array
*args_array
= object
->GetAsArray();
1974 Status::FromErrorStringWithFormatv("Argument definition element "
1975 "{0} is not an array",
1979 args_array
->ForEach(args_adder
);
1980 if (m_args_error
.Fail())
1982 if (this_entry
.empty()) {
1984 Status::FromErrorStringWithFormatv("Argument definition element "
1989 m_arguments
.push_back(this_entry
);
1992 }; // end of arg_array_adder
1993 // Here we actually parse the args definition:
1994 args_array
->ForEach(arg_array_adder
);
1998 ~CommandObjectScriptingObjectParsed() override
= default;
2000 Status
GetOptionsError() { return m_options_error
.Clone(); }
2001 Status
GetArgsError() { return m_args_error
.Clone(); }
2002 bool WantsCompletion() override
{ return true; }
2005 void PrepareOptionsForCompletion(CompletionRequest
&request
,
2006 OptionElementVector
&option_vec
) {
2007 // First, we have to tell the Scripted side to set the values in its
2008 // option store, then we call into the handle_completion passing in
2009 // an array of the args, the arg index and the cursor position in the arg.
2010 // We want the script side to have a chance to clear its state, so tell
2011 // it argument parsing has started:
2012 Options
*options
= GetOptions();
2013 // If there are not options, this will be nullptr, and in that case we
2014 // can just skip setting the options on the scripted side:
2016 m_options
.PrepareOptionsForCompletion(request
, option_vec
, &m_exe_ctx
);
2020 void HandleArgumentCompletion(CompletionRequest
&request
,
2021 OptionElementVector
&option_vec
) override
{
2022 ScriptInterpreter
*scripter
= GetDebugger().GetScriptInterpreter();
2027 // Set up the options values on the scripted side:
2028 PrepareOptionsForCompletion(request
, option_vec
);
2030 // Now we have to make up the argument list.
2031 // The ParseForCompletion only identifies tokens in the m_parsed_line
2032 // it doesn't remove the options leaving only the args as it does for
2033 // the regular Parse, so we have to filter out the option ones using the
2034 // option_element_vector:
2036 Options
*options
= GetOptions();
2037 auto defs
= options
->GetDefinitions();
2039 std::unordered_set
<size_t> option_slots
;
2040 for (const auto &elem
: option_vec
) {
2041 if (elem
.opt_defs_index
== -1)
2043 option_slots
.insert(elem
.opt_pos
);
2044 if (defs
[elem
.opt_defs_index
].option_has_arg
)
2045 option_slots
.insert(elem
.opt_arg_pos
);
2048 std::vector
<llvm::StringRef
> args_vec
;
2049 Args
&args
= request
.GetParsedLine();
2050 size_t num_args
= args
.GetArgumentCount();
2051 size_t cursor_idx
= request
.GetCursorIndex();
2052 size_t args_elem_pos
= cursor_idx
;
2054 for (size_t idx
= 0; idx
< num_args
; idx
++) {
2055 if (option_slots
.count(idx
) == 0)
2056 args_vec
.push_back(args
[idx
].ref());
2057 else if (idx
< cursor_idx
)
2060 StructuredData::DictionarySP completion_dict_sp
=
2061 scripter
->HandleArgumentCompletionForScriptedCommand(
2062 m_cmd_obj_sp
, args_vec
, args_elem_pos
, request
.GetCursorCharPos());
2064 if (!completion_dict_sp
) {
2065 CommandObject::HandleArgumentCompletion(request
, option_vec
);
2069 m_options
.ProcessCompletionDict(request
, completion_dict_sp
);
2072 bool IsRemovable() const override
{ return true; }
2074 ScriptedCommandSynchronicity
GetSynchronicity() { return m_synchro
; }
2076 std::optional
<std::string
> GetRepeatCommand(Args
&args
,
2077 uint32_t index
) override
{
2078 ScriptInterpreter
*scripter
= GetDebugger().GetScriptInterpreter();
2080 return std::nullopt
;
2082 return scripter
->GetRepeatCommandForScriptedCommand(m_cmd_obj_sp
, args
);
2085 llvm::StringRef
GetHelp() override
{
2086 if (m_fetched_help_short
)
2087 return CommandObjectParsed::GetHelp();
2088 ScriptInterpreter
*scripter
= GetDebugger().GetScriptInterpreter();
2090 return CommandObjectParsed::GetHelp();
2091 std::string docstring
;
2092 m_fetched_help_short
=
2093 scripter
->GetShortHelpForCommandObject(m_cmd_obj_sp
, docstring
);
2094 if (!docstring
.empty())
2097 return CommandObjectParsed::GetHelp();
2100 llvm::StringRef
GetHelpLong() override
{
2101 if (m_fetched_help_long
)
2102 return CommandObjectParsed::GetHelpLong();
2104 ScriptInterpreter
*scripter
= GetDebugger().GetScriptInterpreter();
2106 return CommandObjectParsed::GetHelpLong();
2108 std::string docstring
;
2109 m_fetched_help_long
=
2110 scripter
->GetLongHelpForCommandObject(m_cmd_obj_sp
, docstring
);
2111 if (!docstring
.empty())
2112 SetHelpLong(docstring
);
2113 return CommandObjectParsed::GetHelpLong();
2116 Options
*GetOptions() override
{
2117 // CommandObjectParsed requires that a command with no options return
2119 if (m_options
.GetNumOptions() == 0)
2125 void DoExecute(Args
&args
,
2126 CommandReturnObject
&result
) override
{
2127 ScriptInterpreter
*scripter
= GetDebugger().GetScriptInterpreter();
2131 result
.SetStatus(eReturnStatusInvalid
);
2134 !scripter
->RunScriptBasedParsedCommand(m_cmd_obj_sp
, args
,
2135 m_synchro
, result
, error
, m_exe_ctx
)) {
2136 result
.AppendError(error
.AsCString());
2138 // Don't change the status if the command already set it...
2139 if (result
.GetStatus() == eReturnStatusInvalid
) {
2140 if (result
.GetOutputString().empty())
2141 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2143 result
.SetStatus(eReturnStatusSuccessFinishResult
);
2149 StructuredData::GenericSP m_cmd_obj_sp
;
2150 ScriptedCommandSynchronicity m_synchro
;
2151 CommandOptions m_options
;
2152 Status m_options_error
;
2153 Status m_args_error
;
2154 bool m_fetched_help_short
: 1;
2155 bool m_fetched_help_long
: 1;
2158 std::unordered_set
<std::string
>
2159 CommandObjectScriptingObjectParsed::CommandOptions::g_string_storer
;
2161 // CommandObjectCommandsScriptImport
2162 #define LLDB_OPTIONS_script_import
2163 #include "CommandOptions.inc"
2165 class CommandObjectCommandsScriptImport
: public CommandObjectParsed
{
2167 CommandObjectCommandsScriptImport(CommandInterpreter
&interpreter
)
2168 : CommandObjectParsed(interpreter
, "command script import",
2169 "Import a scripting module in LLDB.", nullptr) {
2170 AddSimpleArgumentList(eArgTypeFilename
, eArgRepeatPlus
);
2173 ~CommandObjectCommandsScriptImport() override
= default;
2175 Options
*GetOptions() override
{ return &m_options
; }
2178 class CommandOptions
: public Options
{
2180 CommandOptions() = default;
2182 ~CommandOptions() override
= default;
2184 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
2185 ExecutionContext
*execution_context
) override
{
2187 const int short_option
= m_getopt_table
[option_idx
].val
;
2189 switch (short_option
) {
2194 relative_to_command_file
= true;
2200 llvm_unreachable("Unimplemented option");
2206 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2207 relative_to_command_file
= false;
2210 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2211 return llvm::ArrayRef(g_script_import_options
);
2213 bool relative_to_command_file
= false;
2214 bool silent
= false;
2217 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
2218 if (command
.empty()) {
2219 result
.AppendError("command script import needs one or more arguments");
2223 FileSpec source_dir
= {};
2224 if (m_options
.relative_to_command_file
) {
2225 source_dir
= GetDebugger().GetCommandInterpreter().GetCurrentSourceDir();
2227 result
.AppendError("command script import -c can only be specified "
2228 "from a command file");
2233 for (auto &entry
: command
.entries()) {
2236 LoadScriptOptions options
;
2237 options
.SetInitSession(true);
2238 options
.SetSilent(m_options
.silent
);
2240 // FIXME: this is necessary because CommandObject::CheckRequirements()
2241 // assumes that commands won't ever be recursively invoked, but it's
2242 // actually possible to craft a Python script that does other "command
2243 // script imports" in __lldb_init_module the real fix is to have
2244 // recursive commands possible with a CommandInvocation object separate
2245 // from the CommandObject itself, so that recursive command invocations
2246 // won't stomp on each other (wrt to execution contents, options, and
2249 if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule(
2250 entry
.c_str(), options
, error
, /*module_sp=*/nullptr,
2252 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2254 result
.AppendErrorWithFormat("module importing failed: %s",
2260 CommandOptions m_options
;
2263 #define LLDB_OPTIONS_script_add
2264 #include "CommandOptions.inc"
2266 class CommandObjectCommandsScriptAdd
: public CommandObjectParsed
,
2267 public IOHandlerDelegateMultiline
{
2269 CommandObjectCommandsScriptAdd(CommandInterpreter
&interpreter
)
2270 : CommandObjectParsed(interpreter
, "command script add",
2271 "Add a scripted function as an LLDB command.",
2272 "Add a scripted function as an lldb command. "
2273 "If you provide a single argument, the command "
2274 "will be added at the root level of the command "
2275 "hierarchy. If there are more arguments they "
2276 "must be a path to a user-added container "
2277 "command, and the last element will be the new "
2279 IOHandlerDelegateMultiline("DONE") {
2280 AddSimpleArgumentList(eArgTypeCommand
, eArgRepeatPlus
);
2283 ~CommandObjectCommandsScriptAdd() override
= default;
2285 Options
*GetOptions() override
{ return &m_options
; }
2288 HandleArgumentCompletion(CompletionRequest
&request
,
2289 OptionElementVector
&opt_element_vector
) override
{
2290 CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter
, request
,
2291 opt_element_vector
);
2295 class CommandOptions
: public Options
{
2297 CommandOptions() = default;
2299 ~CommandOptions() override
= default;
2301 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
2302 ExecutionContext
*execution_context
) override
{
2304 const int short_option
= m_getopt_table
[option_idx
].val
;
2306 switch (short_option
) {
2308 if (!option_arg
.empty())
2309 m_funct_name
= std::string(option_arg
);
2312 if (!option_arg
.empty())
2313 m_class_name
= std::string(option_arg
);
2316 if (!option_arg
.empty())
2317 m_short_help
= std::string(option_arg
);
2320 m_overwrite_lazy
= eLazyBoolYes
;
2323 m_parsed_command
= true;
2327 (ScriptedCommandSynchronicity
)OptionArgParser::ToOptionEnum(
2328 option_arg
, GetDefinitions()[option_idx
].enum_values
, 0, error
);
2329 if (!error
.Success())
2330 return Status::FromErrorStringWithFormat(
2331 "unrecognized value for synchronicity '%s'",
2332 option_arg
.str().c_str());
2336 OptionDefinition definition
= GetDefinitions()[option_idx
];
2337 lldb::CompletionType completion_type
=
2338 static_cast<lldb::CompletionType
>(OptionArgParser::ToOptionEnum(
2339 option_arg
, definition
.enum_values
, eNoCompletion
, error
));
2340 if (!error
.Success())
2341 return Status::FromErrorStringWithFormat(
2342 "unrecognized value for command completion type '%s'",
2343 option_arg
.str().c_str());
2344 m_completion_type
= completion_type
;
2347 llvm_unreachable("Unimplemented option");
2353 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2354 m_class_name
.clear();
2355 m_funct_name
.clear();
2356 m_short_help
.clear();
2357 m_completion_type
= eNoCompletion
;
2358 m_overwrite_lazy
= eLazyBoolCalculate
;
2359 m_synchronicity
= eScriptedCommandSynchronicitySynchronous
;
2360 m_parsed_command
= false;
2363 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2364 return llvm::ArrayRef(g_script_add_options
);
2367 // Instance variables to hold the values for command options.
2369 std::string m_class_name
;
2370 std::string m_funct_name
;
2371 std::string m_short_help
;
2372 LazyBool m_overwrite_lazy
= eLazyBoolCalculate
;
2373 ScriptedCommandSynchronicity m_synchronicity
=
2374 eScriptedCommandSynchronicitySynchronous
;
2375 CompletionType m_completion_type
= eNoCompletion
;
2376 bool m_parsed_command
= false;
2379 void IOHandlerActivated(IOHandler
&io_handler
, bool interactive
) override
{
2380 StreamFileSP
output_sp(io_handler
.GetOutputStreamFileSP());
2381 if (output_sp
&& interactive
) {
2382 output_sp
->PutCString(g_python_command_instructions
);
2387 void IOHandlerInputComplete(IOHandler
&io_handler
,
2388 std::string
&data
) override
{
2389 StreamFileSP error_sp
= io_handler
.GetErrorStreamFileSP();
2391 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
2394 lines
.SplitIntoLines(data
);
2395 if (lines
.GetSize() > 0) {
2396 std::string funct_name_str
;
2397 if (interpreter
->GenerateScriptAliasFunction(lines
, funct_name_str
)) {
2398 if (funct_name_str
.empty()) {
2399 error_sp
->Printf("error: unable to obtain a function name, didn't "
2400 "add python command.\n");
2403 // everything should be fine now, let's add this alias
2405 CommandObjectSP
command_obj_sp(new CommandObjectPythonFunction(
2406 m_interpreter
, m_cmd_name
, funct_name_str
, m_short_help
,
2407 m_synchronicity
, m_completion_type
));
2409 Status error
= m_interpreter
.AddUserCommand(
2410 m_cmd_name
, command_obj_sp
, m_overwrite
);
2412 error_sp
->Printf("error: unable to add selected command: '%s'",
2417 llvm::Error llvm_error
= m_container
->LoadUserSubcommand(
2418 m_cmd_name
, command_obj_sp
, m_overwrite
);
2420 error_sp
->Printf("error: unable to add selected command: '%s'",
2421 llvm::toString(std::move(llvm_error
)).c_str());
2428 "error: unable to create function, didn't add python command\n");
2432 error_sp
->Printf("error: empty function, didn't add python command\n");
2437 "error: script interpreter missing, didn't add python command\n");
2441 io_handler
.SetIsDone(true);
2444 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
2445 if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython
) {
2446 result
.AppendError("only scripting language supported for scripted "
2447 "commands is currently Python");
2451 if (command
.GetArgumentCount() == 0) {
2452 result
.AppendError("'command script add' requires at least one argument");
2455 // Store the options in case we get multi-line input, also figure out the
2456 // default if not user supplied:
2457 switch (m_options
.m_overwrite_lazy
) {
2458 case eLazyBoolCalculate
:
2459 m_overwrite
= !GetDebugger().GetCommandInterpreter().GetRequireCommandOverwrite();
2465 m_overwrite
= false;
2469 m_container
= GetCommandInterpreter().VerifyUserMultiwordCmdPath(
2470 command
, true, path_error
);
2472 if (path_error
.Fail()) {
2473 result
.AppendErrorWithFormat("error in command path: %s",
2474 path_error
.AsCString());
2479 // This is getting inserted into the root of the interpreter.
2480 m_cmd_name
= std::string(command
[0].ref());
2482 size_t num_args
= command
.GetArgumentCount();
2483 m_cmd_name
= std::string(command
[num_args
- 1].ref());
2486 m_short_help
.assign(m_options
.m_short_help
);
2487 m_synchronicity
= m_options
.m_synchronicity
;
2488 m_completion_type
= m_options
.m_completion_type
;
2490 // Handle the case where we prompt for the script code first:
2491 if (m_options
.m_class_name
.empty() && m_options
.m_funct_name
.empty()) {
2492 m_interpreter
.GetPythonCommandsFromIOHandler(" ", // Prompt
2493 *this); // IOHandlerDelegate
2497 CommandObjectSP new_cmd_sp
;
2498 if (m_options
.m_class_name
.empty()) {
2499 new_cmd_sp
.reset(new CommandObjectPythonFunction(
2500 m_interpreter
, m_cmd_name
, m_options
.m_funct_name
,
2501 m_options
.m_short_help
, m_synchronicity
, m_completion_type
));
2503 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
2505 result
.AppendError("cannot find ScriptInterpreter");
2509 auto cmd_obj_sp
= interpreter
->CreateScriptCommandObject(
2510 m_options
.m_class_name
.c_str());
2512 result
.AppendErrorWithFormatv("cannot create helper object for: "
2513 "'{0}'", m_options
.m_class_name
);
2517 if (m_options
.m_parsed_command
) {
2518 new_cmd_sp
= CommandObjectScriptingObjectParsed::Create(m_interpreter
,
2519 m_cmd_name
, cmd_obj_sp
, m_synchronicity
, result
);
2520 if (!result
.Succeeded())
2523 new_cmd_sp
.reset(new CommandObjectScriptingObjectRaw(
2524 m_interpreter
, m_cmd_name
, cmd_obj_sp
, m_synchronicity
,
2525 m_completion_type
));
2528 // Assume we're going to succeed...
2529 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2532 m_interpreter
.AddUserCommand(m_cmd_name
, new_cmd_sp
, m_overwrite
);
2533 if (add_error
.Fail())
2534 result
.AppendErrorWithFormat("cannot add command: %s",
2535 add_error
.AsCString());
2537 llvm::Error llvm_error
=
2538 m_container
->LoadUserSubcommand(m_cmd_name
, new_cmd_sp
, m_overwrite
);
2540 result
.AppendErrorWithFormat(
2541 "cannot add command: %s",
2542 llvm::toString(std::move(llvm_error
)).c_str());
2546 CommandOptions m_options
;
2547 std::string m_cmd_name
;
2548 CommandObjectMultiword
*m_container
= nullptr;
2549 std::string m_short_help
;
2550 bool m_overwrite
= false;
2551 ScriptedCommandSynchronicity m_synchronicity
=
2552 eScriptedCommandSynchronicitySynchronous
;
2553 CompletionType m_completion_type
= eNoCompletion
;
2556 // CommandObjectCommandsScriptList
2558 class CommandObjectCommandsScriptList
: public CommandObjectParsed
{
2560 CommandObjectCommandsScriptList(CommandInterpreter
&interpreter
)
2561 : CommandObjectParsed(interpreter
, "command script list",
2562 "List defined top-level scripted commands.",
2565 ~CommandObjectCommandsScriptList() override
= default;
2567 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
2568 m_interpreter
.GetHelp(result
, CommandInterpreter::eCommandTypesUserDef
);
2570 result
.SetStatus(eReturnStatusSuccessFinishResult
);
2574 // CommandObjectCommandsScriptClear
2576 class CommandObjectCommandsScriptClear
: public CommandObjectParsed
{
2578 CommandObjectCommandsScriptClear(CommandInterpreter
&interpreter
)
2579 : CommandObjectParsed(interpreter
, "command script clear",
2580 "Delete all scripted commands.", nullptr) {}
2582 ~CommandObjectCommandsScriptClear() override
= default;
2585 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
2586 m_interpreter
.RemoveAllUser();
2588 result
.SetStatus(eReturnStatusSuccessFinishResult
);
2592 // CommandObjectCommandsScriptDelete
2594 class CommandObjectCommandsScriptDelete
: public CommandObjectParsed
{
2596 CommandObjectCommandsScriptDelete(CommandInterpreter
&interpreter
)
2597 : CommandObjectParsed(
2598 interpreter
, "command script delete",
2599 "Delete a scripted command by specifying the path to the command.",
2601 AddSimpleArgumentList(eArgTypeCommand
, eArgRepeatPlus
);
2604 ~CommandObjectCommandsScriptDelete() override
= default;
2607 HandleArgumentCompletion(CompletionRequest
&request
,
2608 OptionElementVector
&opt_element_vector
) override
{
2609 lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs(
2610 m_interpreter
, request
, opt_element_vector
);
2614 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
2616 llvm::StringRef root_cmd
= command
[0].ref();
2617 size_t num_args
= command
.GetArgumentCount();
2619 if (root_cmd
.empty()) {
2620 result
.AppendErrorWithFormat("empty root command name");
2623 if (!m_interpreter
.HasUserCommands() &&
2624 !m_interpreter
.HasUserMultiwordCommands()) {
2625 result
.AppendErrorWithFormat("can only delete user defined commands, "
2626 "but no user defined commands found");
2630 CommandObjectSP cmd_sp
= m_interpreter
.GetCommandSPExact(root_cmd
);
2632 result
.AppendErrorWithFormat("command '%s' not found.",
2633 command
[0].c_str());
2636 if (!cmd_sp
->IsUserCommand()) {
2637 result
.AppendErrorWithFormat("command '%s' is not a user command.",
2638 command
[0].c_str());
2641 if (cmd_sp
->GetAsMultiwordCommand() && num_args
== 1) {
2642 result
.AppendErrorWithFormat("command '%s' is a multi-word command.\n "
2643 "Delete with \"command container delete\"",
2644 command
[0].c_str());
2648 if (command
.GetArgumentCount() == 1) {
2649 m_interpreter
.RemoveUser(root_cmd
);
2650 result
.SetStatus(eReturnStatusSuccessFinishResult
);
2653 // We're deleting a command from a multiword command. Verify the command
2656 CommandObjectMultiword
*container
=
2657 GetCommandInterpreter().VerifyUserMultiwordCmdPath(command
, true,
2660 result
.AppendErrorWithFormat("could not resolve command path: %s",
2665 // This means that command only had a leaf command, so the container is
2666 // the root. That should have been handled above.
2667 result
.AppendErrorWithFormat("could not find a container for '%s'",
2668 command
[0].c_str());
2671 const char *leaf_cmd
= command
[num_args
- 1].c_str();
2672 llvm::Error llvm_error
=
2673 container
->RemoveUserSubcommand(leaf_cmd
,
2674 /* multiword not okay */ false);
2676 result
.AppendErrorWithFormat(
2677 "could not delete command '%s': %s", leaf_cmd
,
2678 llvm::toString(std::move(llvm_error
)).c_str());
2682 Stream
&out_stream
= result
.GetOutputStream();
2684 out_stream
<< "Deleted command:";
2685 for (size_t idx
= 0; idx
< num_args
; idx
++) {
2687 out_stream
<< command
[idx
].c_str();
2690 result
.SetStatus(eReturnStatusSuccessFinishResult
);
2694 #pragma mark CommandObjectMultiwordCommandsScript
2696 // CommandObjectMultiwordCommandsScript
2698 class CommandObjectMultiwordCommandsScript
: public CommandObjectMultiword
{
2700 CommandObjectMultiwordCommandsScript(CommandInterpreter
&interpreter
)
2701 : CommandObjectMultiword(
2702 interpreter
, "command script",
2703 "Commands for managing custom "
2704 "commands implemented by "
2705 "interpreter scripts.",
2706 "command script <subcommand> [<subcommand-options>]") {
2707 LoadSubCommand("add", CommandObjectSP(
2708 new CommandObjectCommandsScriptAdd(interpreter
)));
2711 CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter
)));
2714 CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter
)));
2715 LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
2719 CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter
)));
2722 ~CommandObjectMultiwordCommandsScript() override
= default;
2725 #pragma mark CommandObjectCommandContainer
2726 #define LLDB_OPTIONS_container_add
2727 #include "CommandOptions.inc"
2729 class CommandObjectCommandsContainerAdd
: public CommandObjectParsed
{
2731 CommandObjectCommandsContainerAdd(CommandInterpreter
&interpreter
)
2732 : CommandObjectParsed(
2733 interpreter
, "command container add",
2734 "Add a container command to lldb. Adding to built-"
2735 "in container commands is not allowed.",
2736 "command container add [[path1]...] container-name") {
2737 AddSimpleArgumentList(eArgTypeCommand
, eArgRepeatPlus
);
2740 ~CommandObjectCommandsContainerAdd() override
= default;
2742 Options
*GetOptions() override
{ return &m_options
; }
2745 HandleArgumentCompletion(CompletionRequest
&request
,
2746 OptionElementVector
&opt_element_vector
) override
{
2747 lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs(
2748 m_interpreter
, request
, opt_element_vector
);
2752 class CommandOptions
: public Options
{
2754 CommandOptions() = default;
2756 ~CommandOptions() override
= default;
2758 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
2759 ExecutionContext
*execution_context
) override
{
2761 const int short_option
= m_getopt_table
[option_idx
].val
;
2763 switch (short_option
) {
2765 if (!option_arg
.empty())
2766 m_short_help
= std::string(option_arg
);
2772 if (!option_arg
.empty())
2773 m_long_help
= std::string(option_arg
);
2776 llvm_unreachable("Unimplemented option");
2782 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2783 m_short_help
.clear();
2784 m_long_help
.clear();
2785 m_overwrite
= false;
2788 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2789 return llvm::ArrayRef(g_container_add_options
);
2792 // Instance variables to hold the values for command options.
2794 std::string m_short_help
;
2795 std::string m_long_help
;
2796 bool m_overwrite
= false;
2798 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
2799 size_t num_args
= command
.GetArgumentCount();
2801 if (num_args
== 0) {
2802 result
.AppendError("no command was specified");
2806 if (num_args
== 1) {
2807 // We're adding this as a root command, so use the interpreter.
2808 const char *cmd_name
= command
.GetArgumentAtIndex(0);
2809 auto cmd_sp
= CommandObjectSP(new CommandObjectMultiword(
2810 GetCommandInterpreter(), cmd_name
, m_options
.m_short_help
.c_str(),
2811 m_options
.m_long_help
.c_str()));
2812 cmd_sp
->GetAsMultiwordCommand()->SetRemovable(true);
2813 Status add_error
= GetCommandInterpreter().AddUserCommand(
2814 cmd_name
, cmd_sp
, m_options
.m_overwrite
);
2815 if (add_error
.Fail()) {
2816 result
.AppendErrorWithFormat("error adding command: %s",
2817 add_error
.AsCString());
2820 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2824 // We're adding this to a subcommand, first find the subcommand:
2826 CommandObjectMultiword
*add_to_me
=
2827 GetCommandInterpreter().VerifyUserMultiwordCmdPath(command
, true,
2831 result
.AppendErrorWithFormat("error adding command: %s",
2832 path_error
.AsCString());
2836 const char *cmd_name
= command
.GetArgumentAtIndex(num_args
- 1);
2837 auto cmd_sp
= CommandObjectSP(new CommandObjectMultiword(
2838 GetCommandInterpreter(), cmd_name
, m_options
.m_short_help
.c_str(),
2839 m_options
.m_long_help
.c_str()));
2840 llvm::Error llvm_error
=
2841 add_to_me
->LoadUserSubcommand(cmd_name
, cmd_sp
, m_options
.m_overwrite
);
2843 result
.AppendErrorWithFormat("error adding subcommand: %s",
2844 llvm::toString(std::move(llvm_error
)).c_str());
2848 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2852 CommandOptions m_options
;
2855 #define LLDB_OPTIONS_multiword_delete
2856 #include "CommandOptions.inc"
2857 class CommandObjectCommandsContainerDelete
: public CommandObjectParsed
{
2859 CommandObjectCommandsContainerDelete(CommandInterpreter
&interpreter
)
2860 : CommandObjectParsed(
2861 interpreter
, "command container delete",
2862 "Delete a container command previously added to "
2864 "command container delete [[path1] ...] container-cmd") {
2865 AddSimpleArgumentList(eArgTypeCommand
, eArgRepeatPlus
);
2868 ~CommandObjectCommandsContainerDelete() override
= default;
2871 HandleArgumentCompletion(CompletionRequest
&request
,
2872 OptionElementVector
&opt_element_vector
) override
{
2873 lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs(
2874 m_interpreter
, request
, opt_element_vector
);
2878 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
2879 size_t num_args
= command
.GetArgumentCount();
2881 if (num_args
== 0) {
2882 result
.AppendError("No command was specified.");
2886 if (num_args
== 1) {
2887 // We're removing a root command, so we need to delete it from the
2889 const char *cmd_name
= command
.GetArgumentAtIndex(0);
2890 // Let's do a little more work here so we can do better error reporting.
2891 CommandInterpreter
&interp
= GetCommandInterpreter();
2892 CommandObjectSP cmd_sp
= interp
.GetCommandSPExact(cmd_name
);
2894 result
.AppendErrorWithFormat("container command %s doesn't exist.",
2898 if (!cmd_sp
->IsUserCommand()) {
2899 result
.AppendErrorWithFormat(
2900 "container command %s is not a user command", cmd_name
);
2903 if (!cmd_sp
->GetAsMultiwordCommand()) {
2904 result
.AppendErrorWithFormat("command %s is not a container command",
2909 bool did_remove
= GetCommandInterpreter().RemoveUserMultiword(cmd_name
);
2911 result
.AppendErrorWithFormat("error removing command %s.", cmd_name
);
2915 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2919 // We're removing a subcommand, first find the subcommand's owner:
2921 CommandObjectMultiword
*container
=
2922 GetCommandInterpreter().VerifyUserMultiwordCmdPath(command
, true,
2926 result
.AppendErrorWithFormat("error removing container command: %s",
2927 path_error
.AsCString());
2930 const char *leaf
= command
.GetArgumentAtIndex(num_args
- 1);
2931 llvm::Error llvm_error
=
2932 container
->RemoveUserSubcommand(leaf
, /* multiword okay */ true);
2934 result
.AppendErrorWithFormat("error removing container command: %s",
2935 llvm::toString(std::move(llvm_error
)).c_str());
2938 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2942 class CommandObjectCommandContainer
: public CommandObjectMultiword
{
2944 CommandObjectCommandContainer(CommandInterpreter
&interpreter
)
2945 : CommandObjectMultiword(
2946 interpreter
, "command container",
2947 "Commands for adding container commands to lldb. "
2948 "Container commands are containers for other commands. You can "
2949 "add nested container commands by specifying a command path, "
2950 "but you can't add commands into the built-in command hierarchy.",
2951 "command container <subcommand> [<subcommand-options>]") {
2952 LoadSubCommand("add", CommandObjectSP(new CommandObjectCommandsContainerAdd(
2956 CommandObjectSP(new CommandObjectCommandsContainerDelete(interpreter
)));
2959 ~CommandObjectCommandContainer() override
= default;
2962 #pragma mark CommandObjectMultiwordCommands
2964 // CommandObjectMultiwordCommands
2966 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
2967 CommandInterpreter
&interpreter
)
2968 : CommandObjectMultiword(interpreter
, "command",
2969 "Commands for managing custom LLDB commands.",
2970 "command <subcommand> [<subcommand-options>]") {
2971 LoadSubCommand("source",
2972 CommandObjectSP(new CommandObjectCommandsSource(interpreter
)));
2973 LoadSubCommand("alias",
2974 CommandObjectSP(new CommandObjectCommandsAlias(interpreter
)));
2975 LoadSubCommand("unalias", CommandObjectSP(
2976 new CommandObjectCommandsUnalias(interpreter
)));
2977 LoadSubCommand("delete",
2978 CommandObjectSP(new CommandObjectCommandsDelete(interpreter
)));
2979 LoadSubCommand("container", CommandObjectSP(new CommandObjectCommandContainer(
2982 "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter
)));
2985 CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter
)));
2988 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;