1 //===-- CommandObjectType.cpp -----------------------------------*- C++ -*-===//
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 "CommandObjectType.h"
11 #include "lldb/Core/Debugger.h"
12 #include "lldb/Core/IOHandler.h"
13 #include "lldb/DataFormatters/DataVisualization.h"
14 #include "lldb/Host/Config.h"
15 #include "lldb/Host/OptionParser.h"
16 #include "lldb/Interpreter/CommandInterpreter.h"
17 #include "lldb/Interpreter/CommandObject.h"
18 #include "lldb/Interpreter/CommandReturnObject.h"
19 #include "lldb/Interpreter/OptionArgParser.h"
20 #include "lldb/Interpreter/OptionGroupFormat.h"
21 #include "lldb/Interpreter/OptionValueBoolean.h"
22 #include "lldb/Interpreter/OptionValueLanguage.h"
23 #include "lldb/Interpreter/OptionValueString.h"
24 #include "lldb/Interpreter/Options.h"
25 #include "lldb/Symbol/Symbol.h"
26 #include "lldb/Target/Language.h"
27 #include "lldb/Target/StackFrame.h"
28 #include "lldb/Target/Target.h"
29 #include "lldb/Target/Thread.h"
30 #include "lldb/Utility/ConstString.h"
31 #include "lldb/Utility/RegularExpression.h"
32 #include "lldb/Utility/StringList.h"
34 #include "llvm/ADT/STLExtras.h"
41 using namespace lldb_private
;
43 class ScriptAddOptions
{
45 TypeSummaryImpl::Flags m_flags
;
46 StringList m_target_types
;
49 std::string m_category
;
51 ScriptAddOptions(const TypeSummaryImpl::Flags
&flags
, bool regx
,
52 ConstString name
, std::string catg
)
53 : m_flags(flags
), m_regex(regx
), m_name(name
), m_category(catg
) {}
55 typedef std::shared_ptr
<ScriptAddOptions
> SharedPointer
;
58 class SynthAddOptions
{
61 bool m_skip_references
;
64 StringList m_target_types
;
65 std::string m_category
;
67 SynthAddOptions(bool sptr
, bool sref
, bool casc
, bool regx
, std::string catg
)
68 : m_skip_pointers(sptr
), m_skip_references(sref
), m_cascade(casc
),
69 m_regex(regx
), m_target_types(), m_category(catg
) {}
71 typedef std::shared_ptr
<SynthAddOptions
> SharedPointer
;
74 static bool WarnOnPotentialUnquotedUnsignedType(Args
&command
,
75 CommandReturnObject
&result
) {
79 for (auto entry
: llvm::enumerate(command
.entries().drop_back())) {
80 if (entry
.value().ref() != "unsigned")
82 auto next
= command
.entries()[entry
.index() + 1].ref();
83 if (next
== "int" || next
== "short" || next
== "char" || next
== "long") {
84 result
.AppendWarningWithFormat(
85 "unsigned %s being treated as two types. if you meant the combined "
87 "name use quotes, as in \"unsigned %s\"\n",
88 next
.str().c_str(), next
.str().c_str());
95 #define LLDB_OPTIONS_type_summary_add
96 #include "CommandOptions.inc"
98 class CommandObjectTypeSummaryAdd
: public CommandObjectParsed
,
99 public IOHandlerDelegateMultiline
{
101 class CommandOptions
: public Options
{
103 CommandOptions(CommandInterpreter
&interpreter
) : Options() {}
105 ~CommandOptions() override
= default;
107 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
108 ExecutionContext
*execution_context
) override
;
110 void OptionParsingStarting(ExecutionContext
*execution_context
) override
;
112 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
113 return llvm::makeArrayRef(g_type_summary_add_options
);
116 // Instance variables to hold the values for command options.
118 TypeSummaryImpl::Flags m_flags
;
120 std::string m_format_string
;
122 std::string m_python_script
;
123 std::string m_python_function
;
124 bool m_is_add_script
;
125 std::string m_category
;
128 CommandOptions m_options
;
130 Options
*GetOptions() override
{ return &m_options
; }
132 bool Execute_ScriptSummary(Args
&command
, CommandReturnObject
&result
);
134 bool Execute_StringSummary(Args
&command
, CommandReturnObject
&result
);
137 enum SummaryFormatType
{ eRegularSummary
, eRegexSummary
, eNamedSummary
};
139 CommandObjectTypeSummaryAdd(CommandInterpreter
&interpreter
);
141 ~CommandObjectTypeSummaryAdd() override
= default;
143 void IOHandlerActivated(IOHandler
&io_handler
, bool interactive
) override
{
144 static const char *g_summary_addreader_instructions
=
145 "Enter your Python command(s). Type 'DONE' to end.\n"
146 "def function (valobj,internal_dict):\n"
147 " \"\"\"valobj: an SBValue which you want to provide a summary "
149 " internal_dict: an LLDB support object not to be used\"\"\"\n";
151 StreamFileSP
output_sp(io_handler
.GetOutputStreamFileSP());
152 if (output_sp
&& interactive
) {
153 output_sp
->PutCString(g_summary_addreader_instructions
);
158 void IOHandlerInputComplete(IOHandler
&io_handler
,
159 std::string
&data
) override
{
160 StreamFileSP error_sp
= io_handler
.GetErrorStreamFileSP();
162 #if LLDB_ENABLE_PYTHON
163 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
166 lines
.SplitIntoLines(data
);
167 if (lines
.GetSize() > 0) {
168 ScriptAddOptions
*options_ptr
=
169 ((ScriptAddOptions
*)io_handler
.GetUserData());
171 ScriptAddOptions::SharedPointer
options(
172 options_ptr
); // this will ensure that we get rid of the pointer
173 // when going out of scope
175 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
177 std::string funct_name_str
;
178 if (interpreter
->GenerateTypeScriptFunction(lines
,
180 if (funct_name_str
.empty()) {
181 error_sp
->Printf("unable to obtain a valid function name from "
182 "the script interpreter.\n");
185 // now I have a valid function name, let's add this as script
186 // for every type in the list
188 TypeSummaryImplSP script_format
;
189 script_format
= std::make_shared
<ScriptSummaryFormat
>(
190 options
->m_flags
, funct_name_str
.c_str(),
191 lines
.CopyList(" ").c_str());
195 for (const std::string
&type_name
: options
->m_target_types
) {
196 CommandObjectTypeSummaryAdd::AddSummary(
197 ConstString(type_name
), script_format
,
199 ? CommandObjectTypeSummaryAdd::eRegexSummary
200 : CommandObjectTypeSummaryAdd::eRegularSummary
),
201 options
->m_category
, &error
);
203 error_sp
->Printf("error: %s", error
.AsCString());
208 if (options
->m_name
) {
209 CommandObjectTypeSummaryAdd::AddSummary(
210 options
->m_name
, script_format
,
211 CommandObjectTypeSummaryAdd::eNamedSummary
,
212 options
->m_category
, &error
);
214 CommandObjectTypeSummaryAdd::AddSummary(
215 options
->m_name
, script_format
,
216 CommandObjectTypeSummaryAdd::eNamedSummary
,
217 options
->m_category
, &error
);
219 error_sp
->Printf("error: %s", error
.AsCString());
223 error_sp
->Printf("error: %s", error
.AsCString());
227 if (error
.AsCString()) {
228 error_sp
->Printf("error: %s", error
.AsCString());
234 error_sp
->Printf("error: unable to generate a function.\n");
238 error_sp
->Printf("error: no script interpreter.\n");
242 error_sp
->Printf("error: internal synchronization information "
243 "missing or invalid.\n");
247 error_sp
->Printf("error: empty function, didn't add python command.\n");
252 "error: script interpreter missing, didn't add python command.\n");
256 io_handler
.SetIsDone(true);
259 static bool AddSummary(ConstString type_name
, lldb::TypeSummaryImplSP entry
,
260 SummaryFormatType type
, std::string category
,
261 Status
*error
= nullptr);
264 bool DoExecute(Args
&command
, CommandReturnObject
&result
) override
;
267 static const char *g_synth_addreader_instructions
=
268 "Enter your Python command(s). Type 'DONE' to end.\n"
269 "You must define a Python class with these methods:\n"
270 " def __init__(self, valobj, dict):\n"
271 " def num_children(self):\n"
272 " def get_child_at_index(self, index):\n"
273 " def get_child_index(self, name):\n"
274 " def update(self):\n"
276 "class synthProvider:\n";
278 #define LLDB_OPTIONS_type_synth_add
279 #include "CommandOptions.inc"
281 class CommandObjectTypeSynthAdd
: public CommandObjectParsed
,
282 public IOHandlerDelegateMultiline
{
284 class CommandOptions
: public Options
{
286 CommandOptions() : Options() {}
288 ~CommandOptions() override
= default;
290 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
291 ExecutionContext
*execution_context
) override
{
293 const int short_option
= m_getopt_table
[option_idx
].val
;
296 switch (short_option
) {
298 m_cascade
= OptionArgParser::ToBoolean(option_arg
, true, &success
);
300 error
.SetErrorStringWithFormat("invalid value for cascade: %s",
301 option_arg
.str().c_str());
304 handwrite_python
= true;
307 m_class_name
= std::string(option_arg
);
308 is_class_based
= true;
311 m_skip_pointers
= true;
314 m_skip_references
= true;
317 m_category
= std::string(option_arg
);
323 llvm_unreachable("Unimplemented option");
329 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
332 m_skip_pointers
= false;
333 m_skip_references
= false;
334 m_category
= "default";
335 is_class_based
= false;
336 handwrite_python
= false;
340 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
341 return llvm::makeArrayRef(g_type_synth_add_options
);
344 // Instance variables to hold the values for command options.
347 bool m_skip_references
;
348 bool m_skip_pointers
;
349 std::string m_class_name
;
351 std::string m_category
;
353 bool handwrite_python
;
357 CommandOptions m_options
;
359 Options
*GetOptions() override
{ return &m_options
; }
361 bool Execute_HandwritePython(Args
&command
, CommandReturnObject
&result
);
363 bool Execute_PythonClass(Args
&command
, CommandReturnObject
&result
);
366 bool DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
367 WarnOnPotentialUnquotedUnsignedType(command
, result
);
369 if (m_options
.handwrite_python
)
370 return Execute_HandwritePython(command
, result
);
371 else if (m_options
.is_class_based
)
372 return Execute_PythonClass(command
, result
);
374 result
.AppendError("must either provide a children list, a Python class "
375 "name, or use -P and type a Python class "
377 result
.SetStatus(eReturnStatusFailed
);
382 void IOHandlerActivated(IOHandler
&io_handler
, bool interactive
) override
{
383 StreamFileSP
output_sp(io_handler
.GetOutputStreamFileSP());
384 if (output_sp
&& interactive
) {
385 output_sp
->PutCString(g_synth_addreader_instructions
);
390 void IOHandlerInputComplete(IOHandler
&io_handler
,
391 std::string
&data
) override
{
392 StreamFileSP error_sp
= io_handler
.GetErrorStreamFileSP();
394 #if LLDB_ENABLE_PYTHON
395 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
398 lines
.SplitIntoLines(data
);
399 if (lines
.GetSize() > 0) {
400 SynthAddOptions
*options_ptr
=
401 ((SynthAddOptions
*)io_handler
.GetUserData());
403 SynthAddOptions::SharedPointer
options(
404 options_ptr
); // this will ensure that we get rid of the pointer
405 // when going out of scope
407 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
409 std::string class_name_str
;
410 if (interpreter
->GenerateTypeSynthClass(lines
, class_name_str
)) {
411 if (class_name_str
.empty()) {
413 "error: unable to obtain a proper name for the class.\n");
416 // everything should be fine now, let's add the synth provider
419 SyntheticChildrenSP synth_provider
;
420 synth_provider
= std::make_shared
<ScriptedSyntheticChildren
>(
421 SyntheticChildren::Flags()
422 .SetCascades(options
->m_cascade
)
423 .SetSkipPointers(options
->m_skip_pointers
)
424 .SetSkipReferences(options
->m_skip_references
),
425 class_name_str
.c_str());
427 lldb::TypeCategoryImplSP category
;
428 DataVisualization::Categories::GetCategory(
429 ConstString(options
->m_category
.c_str()), category
);
433 for (const std::string
&type_name
: options
->m_target_types
) {
434 if (!type_name
.empty()) {
435 if (!CommandObjectTypeSynthAdd::AddSynth(
436 ConstString(type_name
), synth_provider
,
438 ? CommandObjectTypeSynthAdd::eRegexSynth
439 : CommandObjectTypeSynthAdd::eRegularSynth
,
440 options
->m_category
, &error
)) {
441 error_sp
->Printf("error: %s\n", error
.AsCString());
446 error_sp
->Printf("error: invalid type name.\n");
453 error_sp
->Printf("error: unable to generate a class.\n");
457 error_sp
->Printf("error: no script interpreter.\n");
461 error_sp
->Printf("error: internal synchronization data missing.\n");
465 error_sp
->Printf("error: empty function, didn't add python command.\n");
470 "error: script interpreter missing, didn't add python command.\n");
475 io_handler
.SetIsDone(true);
479 enum SynthFormatType
{ eRegularSynth
, eRegexSynth
};
481 CommandObjectTypeSynthAdd(CommandInterpreter
&interpreter
);
483 ~CommandObjectTypeSynthAdd() override
= default;
485 static bool AddSynth(ConstString type_name
, lldb::SyntheticChildrenSP entry
,
486 SynthFormatType type
, std::string category_name
,
490 // CommandObjectTypeFormatAdd
492 #define LLDB_OPTIONS_type_format_add
493 #include "CommandOptions.inc"
495 class CommandObjectTypeFormatAdd
: public CommandObjectParsed
{
497 class CommandOptions
: public OptionGroup
{
499 CommandOptions() : OptionGroup() {}
501 ~CommandOptions() override
= default;
503 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
504 return llvm::makeArrayRef(g_type_format_add_options
);
507 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
509 m_skip_pointers
= false;
510 m_skip_references
= false;
512 m_category
.assign("default");
513 m_custom_type_name
.clear();
516 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_value
,
517 ExecutionContext
*execution_context
) override
{
519 const int short_option
=
520 g_type_format_add_options
[option_idx
].short_option
;
523 switch (short_option
) {
525 m_cascade
= OptionArgParser::ToBoolean(option_value
, true, &success
);
527 error
.SetErrorStringWithFormat("invalid value for cascade: %s",
528 option_value
.str().c_str());
531 m_skip_pointers
= true;
534 m_category
.assign(option_value
);
537 m_skip_references
= true;
543 m_custom_type_name
.assign(option_value
);
546 llvm_unreachable("Unimplemented option");
552 // Instance variables to hold the values for command options.
555 bool m_skip_references
;
556 bool m_skip_pointers
;
558 std::string m_category
;
559 std::string m_custom_type_name
;
562 OptionGroupOptions m_option_group
;
563 OptionGroupFormat m_format_options
;
564 CommandOptions m_command_options
;
566 Options
*GetOptions() override
{ return &m_option_group
; }
569 CommandObjectTypeFormatAdd(CommandInterpreter
&interpreter
)
570 : CommandObjectParsed(interpreter
, "type format add",
571 "Add a new formatting style for a type.", nullptr),
572 m_option_group(), m_format_options(eFormatInvalid
),
573 m_command_options() {
574 CommandArgumentEntry type_arg
;
575 CommandArgumentData type_style_arg
;
577 type_style_arg
.arg_type
= eArgTypeName
;
578 type_style_arg
.arg_repetition
= eArgRepeatPlus
;
580 type_arg
.push_back(type_style_arg
);
582 m_arguments
.push_back(type_arg
);
586 The following examples of 'type format add' refer to this code snippet for context:
589 typedef float Afloat;
591 typedef Afloat Bfloat;
599 Adding default formatting:
601 (lldb) type format add -f hex AInt
602 (lldb) frame variable iy
605 " Produces hexadecimal display of iy, because no formatter is available for Bint and \
606 the one for Aint is used instead."
609 To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains:
612 (lldb) type format add -f hex -C no AInt
614 Similar reasoning applies to this:
616 (lldb) type format add -f hex -C no float -p
619 " All float values and float references are now formatted as hexadecimal, but not \
620 pointers to floats. Nor will it change the default display for Afloat and Bfloat objects.");
622 // Add the "--format" to all options groups
623 m_option_group
.Append(&m_format_options
,
624 OptionGroupFormat::OPTION_GROUP_FORMAT
,
626 m_option_group
.Append(&m_command_options
);
627 m_option_group
.Finalize();
630 ~CommandObjectTypeFormatAdd() override
= default;
633 bool DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
634 const size_t argc
= command
.GetArgumentCount();
637 result
.AppendErrorWithFormat("%s takes one or more args.\n",
639 result
.SetStatus(eReturnStatusFailed
);
643 const Format format
= m_format_options
.GetFormat();
644 if (format
== eFormatInvalid
&&
645 m_command_options
.m_custom_type_name
.empty()) {
646 result
.AppendErrorWithFormat("%s needs a valid format.\n",
648 result
.SetStatus(eReturnStatusFailed
);
652 TypeFormatImplSP entry
;
654 if (m_command_options
.m_custom_type_name
.empty())
655 entry
= std::make_shared
<TypeFormatImpl_Format
>(
656 format
, TypeFormatImpl::Flags()
657 .SetCascades(m_command_options
.m_cascade
)
658 .SetSkipPointers(m_command_options
.m_skip_pointers
)
659 .SetSkipReferences(m_command_options
.m_skip_references
));
661 entry
= std::make_shared
<TypeFormatImpl_EnumType
>(
662 ConstString(m_command_options
.m_custom_type_name
.c_str()),
663 TypeFormatImpl::Flags()
664 .SetCascades(m_command_options
.m_cascade
)
665 .SetSkipPointers(m_command_options
.m_skip_pointers
)
666 .SetSkipReferences(m_command_options
.m_skip_references
));
668 // now I have a valid format, let's add it to every type
670 TypeCategoryImplSP category_sp
;
671 DataVisualization::Categories::GetCategory(
672 ConstString(m_command_options
.m_category
), category_sp
);
676 WarnOnPotentialUnquotedUnsignedType(command
, result
);
678 for (auto &arg_entry
: command
.entries()) {
679 if (arg_entry
.ref().empty()) {
680 result
.AppendError("empty typenames not allowed");
681 result
.SetStatus(eReturnStatusFailed
);
685 ConstString
typeCS(arg_entry
.ref());
686 if (m_command_options
.m_regex
) {
687 RegularExpression
typeRX(arg_entry
.ref());
688 if (!typeRX
.IsValid()) {
690 "regex format error (maybe this is not really a regex?)");
691 result
.SetStatus(eReturnStatusFailed
);
694 category_sp
->GetRegexTypeSummariesContainer()->Delete(typeCS
);
695 category_sp
->GetRegexTypeFormatsContainer()->Add(std::move(typeRX
),
698 category_sp
->GetTypeFormatsContainer()->Add(std::move(typeCS
), entry
);
701 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
702 return result
.Succeeded();
706 #define LLDB_OPTIONS_type_formatter_delete
707 #include "CommandOptions.inc"
709 class CommandObjectTypeFormatterDelete
: public CommandObjectParsed
{
711 class CommandOptions
: public Options
{
713 CommandOptions() : Options() {}
715 ~CommandOptions() override
= default;
717 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
718 ExecutionContext
*execution_context
) override
{
720 const int short_option
= m_getopt_table
[option_idx
].val
;
722 switch (short_option
) {
727 m_category
= std::string(option_arg
);
730 m_language
= Language::GetLanguageTypeFromString(option_arg
);
733 llvm_unreachable("Unimplemented option");
739 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
740 m_delete_all
= false;
741 m_category
= "default";
742 m_language
= lldb::eLanguageTypeUnknown
;
745 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
746 return llvm::makeArrayRef(g_type_formatter_delete_options
);
749 // Instance variables to hold the values for command options.
752 std::string m_category
;
753 lldb::LanguageType m_language
;
756 CommandOptions m_options
;
757 uint32_t m_formatter_kind_mask
;
759 Options
*GetOptions() override
{ return &m_options
; }
762 CommandObjectTypeFormatterDelete(CommandInterpreter
&interpreter
,
763 uint32_t formatter_kind_mask
,
764 const char *name
, const char *help
)
765 : CommandObjectParsed(interpreter
, name
, help
, nullptr), m_options(),
766 m_formatter_kind_mask(formatter_kind_mask
) {
767 CommandArgumentEntry type_arg
;
768 CommandArgumentData type_style_arg
;
770 type_style_arg
.arg_type
= eArgTypeName
;
771 type_style_arg
.arg_repetition
= eArgRepeatPlain
;
773 type_arg
.push_back(type_style_arg
);
775 m_arguments
.push_back(type_arg
);
778 ~CommandObjectTypeFormatterDelete() override
= default;
781 virtual bool FormatterSpecificDeletion(ConstString typeCS
) { return false; }
783 bool DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
784 const size_t argc
= command
.GetArgumentCount();
787 result
.AppendErrorWithFormat("%s takes 1 arg.\n", m_cmd_name
.c_str());
788 result
.SetStatus(eReturnStatusFailed
);
792 const char *typeA
= command
.GetArgumentAtIndex(0);
793 ConstString
typeCS(typeA
);
796 result
.AppendError("empty typenames not allowed");
797 result
.SetStatus(eReturnStatusFailed
);
801 if (m_options
.m_delete_all
) {
802 DataVisualization::Categories::ForEach(
803 [this, typeCS
](const lldb::TypeCategoryImplSP
&category_sp
) -> bool {
804 category_sp
->Delete(typeCS
, m_formatter_kind_mask
);
807 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
808 return result
.Succeeded();
811 bool delete_category
= false;
812 bool extra_deletion
= false;
814 if (m_options
.m_language
!= lldb::eLanguageTypeUnknown
) {
815 lldb::TypeCategoryImplSP category
;
816 DataVisualization::Categories::GetCategory(m_options
.m_language
,
819 delete_category
= category
->Delete(typeCS
, m_formatter_kind_mask
);
820 extra_deletion
= FormatterSpecificDeletion(typeCS
);
822 lldb::TypeCategoryImplSP category
;
823 DataVisualization::Categories::GetCategory(
824 ConstString(m_options
.m_category
.c_str()), category
);
826 delete_category
= category
->Delete(typeCS
, m_formatter_kind_mask
);
827 extra_deletion
= FormatterSpecificDeletion(typeCS
);
830 if (delete_category
|| extra_deletion
) {
831 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
832 return result
.Succeeded();
834 result
.AppendErrorWithFormat("no custom formatter for %s.\n", typeA
);
835 result
.SetStatus(eReturnStatusFailed
);
841 #define LLDB_OPTIONS_type_formatter_clear
842 #include "CommandOptions.inc"
844 class CommandObjectTypeFormatterClear
: public CommandObjectParsed
{
846 class CommandOptions
: public Options
{
848 CommandOptions() : Options() {}
850 ~CommandOptions() override
= default;
852 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
853 ExecutionContext
*execution_context
) override
{
855 const int short_option
= m_getopt_table
[option_idx
].val
;
857 switch (short_option
) {
862 llvm_unreachable("Unimplemented option");
868 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
869 m_delete_all
= false;
872 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
873 return llvm::makeArrayRef(g_type_formatter_clear_options
);
876 // Instance variables to hold the values for command options.
880 CommandOptions m_options
;
881 uint32_t m_formatter_kind_mask
;
883 Options
*GetOptions() override
{ return &m_options
; }
886 CommandObjectTypeFormatterClear(CommandInterpreter
&interpreter
,
887 uint32_t formatter_kind_mask
,
888 const char *name
, const char *help
)
889 : CommandObjectParsed(interpreter
, name
, help
, nullptr), m_options(),
890 m_formatter_kind_mask(formatter_kind_mask
) {}
892 ~CommandObjectTypeFormatterClear() override
= default;
895 virtual void FormatterSpecificDeletion() {}
897 bool DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
898 if (m_options
.m_delete_all
) {
899 DataVisualization::Categories::ForEach(
900 [this](const TypeCategoryImplSP
&category_sp
) -> bool {
901 category_sp
->Clear(m_formatter_kind_mask
);
905 lldb::TypeCategoryImplSP category
;
906 if (command
.GetArgumentCount() > 0) {
907 const char *cat_name
= command
.GetArgumentAtIndex(0);
908 ConstString
cat_nameCS(cat_name
);
909 DataVisualization::Categories::GetCategory(cat_nameCS
, category
);
911 DataVisualization::Categories::GetCategory(ConstString(nullptr),
914 category
->Clear(m_formatter_kind_mask
);
917 FormatterSpecificDeletion();
919 result
.SetStatus(eReturnStatusSuccessFinishResult
);
920 return result
.Succeeded();
924 // CommandObjectTypeFormatDelete
926 class CommandObjectTypeFormatDelete
: public CommandObjectTypeFormatterDelete
{
928 CommandObjectTypeFormatDelete(CommandInterpreter
&interpreter
)
929 : CommandObjectTypeFormatterDelete(
931 eFormatCategoryItemValue
| eFormatCategoryItemRegexValue
,
932 "type format delete",
933 "Delete an existing formatting style for a type.") {}
935 ~CommandObjectTypeFormatDelete() override
= default;
938 // CommandObjectTypeFormatClear
940 class CommandObjectTypeFormatClear
: public CommandObjectTypeFormatterClear
{
942 CommandObjectTypeFormatClear(CommandInterpreter
&interpreter
)
943 : CommandObjectTypeFormatterClear(
945 eFormatCategoryItemValue
| eFormatCategoryItemRegexValue
,
946 "type format clear", "Delete all existing format styles.") {}
949 #define LLDB_OPTIONS_type_formatter_list
950 #include "CommandOptions.inc"
952 template <typename FormatterType
>
953 class CommandObjectTypeFormatterList
: public CommandObjectParsed
{
954 typedef typename
FormatterType::SharedPointer FormatterSharedPointer
;
956 class CommandOptions
: public Options
{
959 : Options(), m_category_regex("", ""),
960 m_category_language(lldb::eLanguageTypeUnknown
,
961 lldb::eLanguageTypeUnknown
) {}
963 ~CommandOptions() override
= default;
965 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
966 ExecutionContext
*execution_context
) override
{
968 const int short_option
= m_getopt_table
[option_idx
].val
;
969 switch (short_option
) {
971 m_category_regex
.SetCurrentValue(option_arg
);
972 m_category_regex
.SetOptionWasSet();
975 error
= m_category_language
.SetValueFromString(option_arg
);
977 m_category_language
.SetOptionWasSet();
980 llvm_unreachable("Unimplemented option");
986 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
987 m_category_regex
.Clear();
988 m_category_language
.Clear();
991 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
992 return llvm::makeArrayRef(g_type_formatter_list_options
);
995 // Instance variables to hold the values for command options.
997 OptionValueString m_category_regex
;
998 OptionValueLanguage m_category_language
;
1001 CommandOptions m_options
;
1003 Options
*GetOptions() override
{ return &m_options
; }
1006 CommandObjectTypeFormatterList(CommandInterpreter
&interpreter
,
1007 const char *name
, const char *help
)
1008 : CommandObjectParsed(interpreter
, name
, help
, nullptr), m_options() {
1009 CommandArgumentEntry type_arg
;
1010 CommandArgumentData type_style_arg
;
1012 type_style_arg
.arg_type
= eArgTypeName
;
1013 type_style_arg
.arg_repetition
= eArgRepeatOptional
;
1015 type_arg
.push_back(type_style_arg
);
1017 m_arguments
.push_back(type_arg
);
1020 ~CommandObjectTypeFormatterList() override
= default;
1023 virtual bool FormatterSpecificList(CommandReturnObject
&result
) {
1027 bool DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1028 const size_t argc
= command
.GetArgumentCount();
1030 std::unique_ptr
<RegularExpression
> category_regex
;
1031 std::unique_ptr
<RegularExpression
> formatter_regex
;
1033 if (m_options
.m_category_regex
.OptionWasSet()) {
1034 category_regex
.reset(new RegularExpression(
1035 m_options
.m_category_regex
.GetCurrentValueAsRef()));
1036 if (!category_regex
->IsValid()) {
1037 result
.AppendErrorWithFormat(
1038 "syntax error in category regular expression '%s'",
1039 m_options
.m_category_regex
.GetCurrentValueAsRef().str().c_str());
1040 result
.SetStatus(eReturnStatusFailed
);
1046 const char *arg
= command
.GetArgumentAtIndex(0);
1047 formatter_regex
.reset(
1048 new RegularExpression(llvm::StringRef::withNullAsEmpty(arg
)));
1049 if (!formatter_regex
->IsValid()) {
1050 result
.AppendErrorWithFormat("syntax error in regular expression '%s'",
1052 result
.SetStatus(eReturnStatusFailed
);
1057 bool any_printed
= false;
1059 auto category_closure
=
1060 [&result
, &formatter_regex
,
1061 &any_printed
](const lldb::TypeCategoryImplSP
&category
) -> void {
1062 result
.GetOutputStream().Printf(
1063 "-----------------------\nCategory: %s%s\n-----------------------\n",
1064 category
->GetName(), category
->IsEnabled() ? "" : " (disabled)");
1066 TypeCategoryImpl::ForEachCallbacks
<FormatterType
> foreach
;
1068 .SetExact([&result
, &formatter_regex
, &any_printed
](
1070 const FormatterSharedPointer
&format_sp
) -> bool {
1071 if (formatter_regex
) {
1073 if (name
.GetStringRef() == formatter_regex
->GetText()) {
1075 } else if (formatter_regex
->Execute(name
.GetStringRef())) {
1084 result
.GetOutputStream().Printf("%s: %s\n", name
.AsCString(),
1085 format_sp
->GetDescription().c_str());
1090 .SetWithRegex([&result
, &formatter_regex
, &any_printed
](
1091 const RegularExpression
®ex
,
1092 const FormatterSharedPointer
&format_sp
) -> bool {
1093 if (formatter_regex
) {
1095 if (regex
.GetText() == formatter_regex
->GetText()) {
1097 } else if (formatter_regex
->Execute(regex
.GetText())) {
1106 result
.GetOutputStream().Printf("%s: %s\n",
1107 regex
.GetText().str().c_str(),
1108 format_sp
->GetDescription().c_str());
1112 category
->ForEach(foreach
);
1115 if (m_options
.m_category_language
.OptionWasSet()) {
1116 lldb::TypeCategoryImplSP category_sp
;
1117 DataVisualization::Categories::GetCategory(
1118 m_options
.m_category_language
.GetCurrentValue(), category_sp
);
1120 category_closure(category_sp
);
1122 DataVisualization::Categories::ForEach(
1123 [&category_regex
, &category_closure
](
1124 const lldb::TypeCategoryImplSP
&category
) -> bool {
1125 if (category_regex
) {
1127 if (category
->GetName() == category_regex
->GetText()) {
1129 } else if (category_regex
->Execute(
1130 llvm::StringRef::withNullAsEmpty(
1131 category
->GetName()))) {
1139 category_closure(category
);
1144 any_printed
= FormatterSpecificList(result
) | any_printed
;
1148 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1150 result
.GetOutputStream().PutCString("no matching results found.\n");
1151 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1153 return result
.Succeeded();
1157 // CommandObjectTypeFormatList
1159 class CommandObjectTypeFormatList
1160 : public CommandObjectTypeFormatterList
<TypeFormatImpl
> {
1162 CommandObjectTypeFormatList(CommandInterpreter
&interpreter
)
1163 : CommandObjectTypeFormatterList(interpreter
, "type format list",
1164 "Show a list of current formats.") {}
1167 Status
CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue(
1168 uint32_t option_idx
, llvm::StringRef option_arg
,
1169 ExecutionContext
*execution_context
) {
1171 const int short_option
= m_getopt_table
[option_idx
].val
;
1174 switch (short_option
) {
1176 m_flags
.SetCascades(OptionArgParser::ToBoolean(option_arg
, true, &success
));
1178 error
.SetErrorStringWithFormat("invalid value for cascade: %s",
1179 option_arg
.str().c_str());
1182 m_flags
.SetDontShowChildren(false);
1185 m_flags
.SetHideEmptyAggregates(true);
1188 m_flags
.SetDontShowValue(true);
1191 m_flags
.SetShowMembersOneLiner(true);
1194 m_format_string
= std::string(option_arg
);
1197 m_flags
.SetSkipPointers(true);
1200 m_flags
.SetSkipReferences(true);
1206 m_name
.SetString(option_arg
);
1209 m_python_script
= option_arg
;
1210 m_is_add_script
= true;
1213 m_python_function
= option_arg
;
1214 m_is_add_script
= true;
1217 m_is_add_script
= true;
1220 m_category
= std::string(option_arg
);
1223 m_flags
.SetHideItemNames(true);
1226 llvm_unreachable("Unimplemented option");
1232 void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting(
1233 ExecutionContext
*execution_context
) {
1234 m_flags
.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
1235 m_flags
.SetShowMembersOneLiner(false)
1236 .SetSkipPointers(false)
1237 .SetSkipReferences(false)
1238 .SetHideItemNames(false);
1242 m_python_script
= "";
1243 m_python_function
= "";
1244 m_format_string
= "";
1245 m_is_add_script
= false;
1246 m_category
= "default";
1249 #if LLDB_ENABLE_PYTHON
1251 bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary(
1252 Args
&command
, CommandReturnObject
&result
) {
1253 const size_t argc
= command
.GetArgumentCount();
1255 if (argc
< 1 && !m_options
.m_name
) {
1256 result
.AppendErrorWithFormat("%s takes one or more args.\n",
1257 m_cmd_name
.c_str());
1258 result
.SetStatus(eReturnStatusFailed
);
1262 TypeSummaryImplSP script_format
;
1264 if (!m_options
.m_python_function
1265 .empty()) // we have a Python function ready to use
1267 const char *funct_name
= m_options
.m_python_function
.c_str();
1268 if (!funct_name
|| !funct_name
[0]) {
1269 result
.AppendError("function name empty.\n");
1270 result
.SetStatus(eReturnStatusFailed
);
1275 (" " + m_options
.m_python_function
+ "(valobj,internal_dict)");
1277 script_format
= std::make_shared
<ScriptSummaryFormat
>(
1278 m_options
.m_flags
, funct_name
, code
.c_str());
1280 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
1282 if (interpreter
&& !interpreter
->CheckObjectExists(funct_name
))
1283 result
.AppendWarningWithFormat(
1284 "The provided function \"%s\" does not exist - "
1285 "please define it before attempting to use this summary.\n",
1287 } else if (!m_options
.m_python_script
1288 .empty()) // we have a quick 1-line script, just use it
1290 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
1292 result
.AppendError("script interpreter missing - unable to generate "
1293 "function wrapper.\n");
1294 result
.SetStatus(eReturnStatusFailed
);
1297 StringList funct_sl
;
1298 funct_sl
<< m_options
.m_python_script
.c_str();
1299 std::string funct_name_str
;
1300 if (!interpreter
->GenerateTypeScriptFunction(funct_sl
, funct_name_str
)) {
1301 result
.AppendError("unable to generate function wrapper.\n");
1302 result
.SetStatus(eReturnStatusFailed
);
1305 if (funct_name_str
.empty()) {
1307 "script interpreter failed to generate a valid function name.\n");
1308 result
.SetStatus(eReturnStatusFailed
);
1312 std::string code
= " " + m_options
.m_python_script
;
1314 script_format
= std::make_shared
<ScriptSummaryFormat
>(
1315 m_options
.m_flags
, funct_name_str
.c_str(), code
.c_str());
1317 // Use an IOHandler to grab Python code from the user
1318 ScriptAddOptions
*options
=
1319 new ScriptAddOptions(m_options
.m_flags
, m_options
.m_regex
,
1320 m_options
.m_name
, m_options
.m_category
);
1322 for (auto &entry
: command
.entries()) {
1323 if (entry
.ref().empty()) {
1324 result
.AppendError("empty typenames not allowed");
1325 result
.SetStatus(eReturnStatusFailed
);
1329 options
->m_target_types
<< entry
.ref();
1332 m_interpreter
.GetPythonCommandsFromIOHandler(
1334 *this, // IOHandlerDelegate
1335 options
); // Baton for the "io_handler" that will be passed back into
1336 // our IOHandlerDelegate functions
1337 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1339 return result
.Succeeded();
1342 // if I am here, script_format must point to something good, so I can add
1343 // that as a script summary to all interested parties
1347 for (auto &entry
: command
.entries()) {
1348 CommandObjectTypeSummaryAdd::AddSummary(
1349 ConstString(entry
.ref()), script_format
,
1350 (m_options
.m_regex
? eRegexSummary
: eRegularSummary
),
1351 m_options
.m_category
, &error
);
1353 result
.AppendError(error
.AsCString());
1354 result
.SetStatus(eReturnStatusFailed
);
1359 if (m_options
.m_name
) {
1360 AddSummary(m_options
.m_name
, script_format
, eNamedSummary
,
1361 m_options
.m_category
, &error
);
1363 result
.AppendError(error
.AsCString());
1364 result
.AppendError("added to types, but not given a name");
1365 result
.SetStatus(eReturnStatusFailed
);
1370 return result
.Succeeded();
1375 bool CommandObjectTypeSummaryAdd::Execute_StringSummary(
1376 Args
&command
, CommandReturnObject
&result
) {
1377 const size_t argc
= command
.GetArgumentCount();
1379 if (argc
< 1 && !m_options
.m_name
) {
1380 result
.AppendErrorWithFormat("%s takes one or more args.\n",
1381 m_cmd_name
.c_str());
1382 result
.SetStatus(eReturnStatusFailed
);
1386 if (!m_options
.m_flags
.GetShowMembersOneLiner() &&
1387 m_options
.m_format_string
.empty()) {
1388 result
.AppendError("empty summary strings not allowed");
1389 result
.SetStatus(eReturnStatusFailed
);
1393 const char *format_cstr
= (m_options
.m_flags
.GetShowMembersOneLiner()
1395 : m_options
.m_format_string
.c_str());
1397 // ${var%S} is an endless recursion, prevent it
1398 if (strcmp(format_cstr
, "${var%S}") == 0) {
1399 result
.AppendError("recursive summary not allowed");
1400 result
.SetStatus(eReturnStatusFailed
);
1404 std::unique_ptr
<StringSummaryFormat
> string_format(
1405 new StringSummaryFormat(m_options
.m_flags
, format_cstr
));
1406 if (!string_format
) {
1407 result
.AppendError("summary creation failed");
1408 result
.SetStatus(eReturnStatusFailed
);
1411 if (string_format
->m_error
.Fail()) {
1412 result
.AppendErrorWithFormat("syntax error: %s",
1413 string_format
->m_error
.AsCString("<unknown>"));
1414 result
.SetStatus(eReturnStatusFailed
);
1417 lldb::TypeSummaryImplSP
entry(string_format
.release());
1419 // now I have a valid format, let's add it to every type
1421 for (auto &arg_entry
: command
.entries()) {
1422 if (arg_entry
.ref().empty()) {
1423 result
.AppendError("empty typenames not allowed");
1424 result
.SetStatus(eReturnStatusFailed
);
1427 ConstString
typeCS(arg_entry
.ref());
1429 AddSummary(typeCS
, entry
,
1430 (m_options
.m_regex
? eRegexSummary
: eRegularSummary
),
1431 m_options
.m_category
, &error
);
1434 result
.AppendError(error
.AsCString());
1435 result
.SetStatus(eReturnStatusFailed
);
1440 if (m_options
.m_name
) {
1441 AddSummary(m_options
.m_name
, entry
, eNamedSummary
, m_options
.m_category
,
1444 result
.AppendError(error
.AsCString());
1445 result
.AppendError("added to types, but not given a name");
1446 result
.SetStatus(eReturnStatusFailed
);
1451 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1452 return result
.Succeeded();
1455 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd(
1456 CommandInterpreter
&interpreter
)
1457 : CommandObjectParsed(interpreter
, "type summary add",
1458 "Add a new summary style for a type.", nullptr),
1459 IOHandlerDelegateMultiline("DONE"), m_options(interpreter
) {
1460 CommandArgumentEntry type_arg
;
1461 CommandArgumentData type_style_arg
;
1463 type_style_arg
.arg_type
= eArgTypeName
;
1464 type_style_arg
.arg_repetition
= eArgRepeatPlus
;
1466 type_arg
.push_back(type_style_arg
);
1468 m_arguments
.push_back(type_arg
);
1472 The following examples of 'type summary add' refer to this code snippet for context:
1478 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
1480 JustADemo demo_instance(42, 3.14);
1482 typedef JustADemo NewDemo;
1483 NewDemo new_demo_instance(42, 3.14);
1485 (lldb) type summary add --summary-string "the answer is $
{*var
.ptr
}" JustADemo
1487 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is
42"
1489 (lldb) type summary add --summary-string "the answer is $
{*var
.ptr
}, and the question is $
{var
.value
}" JustADemo
1491 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is
42 and the question is
3.14"
1494 "Alternatively, you could define formatting for all pointers to integers and \
1495 rely on that when formatting JustADemo to obtain the same result:"
1498 (lldb) type summary add --summary-string "$
{var
%V
} -> $
{*var
}" "int *"
1499 (lldb) type summary add --summary-string "the answer is $
{var
.ptr
}, and the question is $
{var
.value
}" JustADemo
1502 "Type summaries are automatically applied to derived typedefs, so the examples \
1503 above apply to both JustADemo and NewDemo. The cascade option can be used to \
1504 suppress this behavior:"
1507 (lldb) type summary add --summary-string "$
{var
.ptr
}, $
{var
.value
},{$
{var
.byte
}}" JustADemo -C no
1509 The summary will now be used for values of JustADemo but not NewDemo.
1512 "By default summaries are shown for pointers and references to values of the \
1513 specified type. To suppress formatting for pointers use the -p option, or apply \
1514 the corresponding -r option to suppress formatting for references:"
1517 (lldb) type summary add -p -r --summary-string "$
{var
.ptr
}, $
{var
.value
},{$
{var
.byte
}}" JustADemo
1520 "One-line summaries including all fields in a type can be inferred without supplying an \
1521 explicit summary string by passing the -c option:"
1524 (lldb) type summary add -c JustADemo
1525 (lldb) frame variable demo_instance
1526 (ptr=<address>, value=3.14)
1529 "Type summaries normally suppress the nested display of individual fields. To \
1530 supply a summary to supplement the default structure add the -e option:"
1533 (lldb) type summary add -e --summary-string "*ptr
= $
{*var
.ptr
}" JustADemo
1536 "Now when displaying JustADemo values the int* is displayed, followed by the \
1537 standard LLDB sequence of children, one per line:"
1546 "You can also add summaries written in Python. These scripts use lldb public API to \
1547 gather information from your variables and produce a meaningful summary. To start a \
1548 multi-line script use the -P option. The function declaration will be displayed along with \
1549 a comment describing the two arguments. End your script with the word 'DONE' on a line by \
1553 (lldb) type summary add JustADemo -P
1554 def function (valobj,internal_dict):
1555 """valobj
: an SBValue which you want to provide a summary
for
1556 internal_dict
: an LLDB support object
not to be used
"""
1557 value = valobj.GetChildMemberWithName('value');
1558 return 'My value is ' + value.GetValue();
1561 Alternatively, the -o option can be used when providing a simple one-line Python script:
1563 (lldb) type summary add JustADemo -o "value
= valobj
.GetChildMemberWithName('value'); return 'My value is ' + value
.GetValue();")");
1566 bool CommandObjectTypeSummaryAdd::DoExecute(Args
&command
,
1567 CommandReturnObject
&result
) {
1568 WarnOnPotentialUnquotedUnsignedType(command
, result
);
1570 if (m_options
.m_is_add_script
) {
1571 #if LLDB_ENABLE_PYTHON
1572 return Execute_ScriptSummary(command
, result
);
1574 result
.AppendError("python is disabled");
1575 result
.SetStatus(eReturnStatusFailed
);
1580 return Execute_StringSummary(command
, result
);
1583 static bool FixArrayTypeNameWithRegex(ConstString
&type_name
) {
1584 llvm::StringRef
type_name_ref(type_name
.GetStringRef());
1586 if (type_name_ref
.endswith("[]")) {
1587 std::string
type_name_str(type_name
.GetCString());
1588 type_name_str
.resize(type_name_str
.length() - 2);
1589 if (type_name_str
.back() != ' ')
1590 type_name_str
.append(" \\[[0-9]+\\]");
1592 type_name_str
.append("\\[[0-9]+\\]");
1593 type_name
.SetCString(type_name_str
.c_str());
1599 bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name
,
1600 TypeSummaryImplSP entry
,
1601 SummaryFormatType type
,
1602 std::string category_name
,
1604 lldb::TypeCategoryImplSP category
;
1605 DataVisualization::Categories::GetCategory(ConstString(category_name
.c_str()),
1608 if (type
== eRegularSummary
) {
1609 if (FixArrayTypeNameWithRegex(type_name
))
1610 type
= eRegexSummary
;
1613 if (type
== eRegexSummary
) {
1614 RegularExpression
typeRX(type_name
.GetStringRef());
1615 if (!typeRX
.IsValid()) {
1617 error
->SetErrorString(
1618 "regex format error (maybe this is not really a regex?)");
1622 category
->GetRegexTypeSummariesContainer()->Delete(type_name
);
1623 category
->GetRegexTypeSummariesContainer()->Add(std::move(typeRX
), entry
);
1626 } else if (type
== eNamedSummary
) {
1627 // system named summaries do not exist (yet?)
1628 DataVisualization::NamedSummaryFormats::Add(type_name
, entry
);
1631 category
->GetTypeSummariesContainer()->Add(std::move(type_name
), entry
);
1636 // CommandObjectTypeSummaryDelete
1638 class CommandObjectTypeSummaryDelete
: public CommandObjectTypeFormatterDelete
{
1640 CommandObjectTypeSummaryDelete(CommandInterpreter
&interpreter
)
1641 : CommandObjectTypeFormatterDelete(
1643 eFormatCategoryItemSummary
| eFormatCategoryItemRegexSummary
,
1644 "type summary delete", "Delete an existing summary for a type.") {}
1646 ~CommandObjectTypeSummaryDelete() override
= default;
1649 bool FormatterSpecificDeletion(ConstString typeCS
) override
{
1650 if (m_options
.m_language
!= lldb::eLanguageTypeUnknown
)
1652 return DataVisualization::NamedSummaryFormats::Delete(typeCS
);
1656 class CommandObjectTypeSummaryClear
: public CommandObjectTypeFormatterClear
{
1658 CommandObjectTypeSummaryClear(CommandInterpreter
&interpreter
)
1659 : CommandObjectTypeFormatterClear(
1661 eFormatCategoryItemSummary
| eFormatCategoryItemRegexSummary
,
1662 "type summary clear", "Delete all existing summaries.") {}
1665 void FormatterSpecificDeletion() override
{
1666 DataVisualization::NamedSummaryFormats::Clear();
1670 // CommandObjectTypeSummaryList
1672 class CommandObjectTypeSummaryList
1673 : public CommandObjectTypeFormatterList
<TypeSummaryImpl
> {
1675 CommandObjectTypeSummaryList(CommandInterpreter
&interpreter
)
1676 : CommandObjectTypeFormatterList(interpreter
, "type summary list",
1677 "Show a list of current summaries.") {}
1680 bool FormatterSpecificList(CommandReturnObject
&result
) override
{
1681 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) {
1682 result
.GetOutputStream().Printf("Named summaries:\n");
1683 DataVisualization::NamedSummaryFormats::ForEach(
1684 [&result
](ConstString name
,
1685 const TypeSummaryImplSP
&summary_sp
) -> bool {
1686 result
.GetOutputStream().Printf(
1687 "%s: %s\n", name
.AsCString(),
1688 summary_sp
->GetDescription().c_str());
1697 // CommandObjectTypeCategoryDefine
1698 #define LLDB_OPTIONS_type_category_define
1699 #include "CommandOptions.inc"
1701 class CommandObjectTypeCategoryDefine
: public CommandObjectParsed
{
1702 class CommandOptions
: public Options
{
1705 : Options(), m_define_enabled(false, false),
1706 m_cate_language(eLanguageTypeUnknown
, eLanguageTypeUnknown
) {}
1708 ~CommandOptions() override
= default;
1710 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1711 ExecutionContext
*execution_context
) override
{
1713 const int short_option
= m_getopt_table
[option_idx
].val
;
1715 switch (short_option
) {
1717 m_define_enabled
.SetValueFromString(llvm::StringRef("true"));
1720 error
= m_cate_language
.SetValueFromString(option_arg
);
1723 llvm_unreachable("Unimplemented option");
1729 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1730 m_define_enabled
.Clear();
1731 m_cate_language
.Clear();
1734 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1735 return llvm::makeArrayRef(g_type_category_define_options
);
1738 // Instance variables to hold the values for command options.
1740 OptionValueBoolean m_define_enabled
;
1741 OptionValueLanguage m_cate_language
;
1744 CommandOptions m_options
;
1746 Options
*GetOptions() override
{ return &m_options
; }
1749 CommandObjectTypeCategoryDefine(CommandInterpreter
&interpreter
)
1750 : CommandObjectParsed(interpreter
, "type category define",
1751 "Define a new category as a source of formatters.",
1754 CommandArgumentEntry type_arg
;
1755 CommandArgumentData type_style_arg
;
1757 type_style_arg
.arg_type
= eArgTypeName
;
1758 type_style_arg
.arg_repetition
= eArgRepeatPlus
;
1760 type_arg
.push_back(type_style_arg
);
1762 m_arguments
.push_back(type_arg
);
1765 ~CommandObjectTypeCategoryDefine() override
= default;
1768 bool DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1769 const size_t argc
= command
.GetArgumentCount();
1772 result
.AppendErrorWithFormat("%s takes 1 or more args.\n",
1773 m_cmd_name
.c_str());
1774 result
.SetStatus(eReturnStatusFailed
);
1778 for (auto &entry
: command
.entries()) {
1779 TypeCategoryImplSP category_sp
;
1780 if (DataVisualization::Categories::GetCategory(ConstString(entry
.ref()),
1783 category_sp
->AddLanguage(m_options
.m_cate_language
.GetCurrentValue());
1784 if (m_options
.m_define_enabled
.GetCurrentValue())
1785 DataVisualization::Categories::Enable(category_sp
,
1786 TypeCategoryMap::Default
);
1790 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1791 return result
.Succeeded();
1795 // CommandObjectTypeCategoryEnable
1796 #define LLDB_OPTIONS_type_category_enable
1797 #include "CommandOptions.inc"
1799 class CommandObjectTypeCategoryEnable
: public CommandObjectParsed
{
1800 class CommandOptions
: public Options
{
1802 CommandOptions() : Options() {}
1804 ~CommandOptions() override
= default;
1806 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1807 ExecutionContext
*execution_context
) override
{
1809 const int short_option
= m_getopt_table
[option_idx
].val
;
1811 switch (short_option
) {
1813 if (!option_arg
.empty()) {
1814 m_language
= Language::GetLanguageTypeFromString(option_arg
);
1815 if (m_language
== lldb::eLanguageTypeUnknown
)
1816 error
.SetErrorStringWithFormat("unrecognized language '%s'",
1817 option_arg
.str().c_str());
1821 llvm_unreachable("Unimplemented option");
1827 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1828 m_language
= lldb::eLanguageTypeUnknown
;
1831 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1832 return llvm::makeArrayRef(g_type_category_enable_options
);
1835 // Instance variables to hold the values for command options.
1837 lldb::LanguageType m_language
;
1840 CommandOptions m_options
;
1842 Options
*GetOptions() override
{ return &m_options
; }
1845 CommandObjectTypeCategoryEnable(CommandInterpreter
&interpreter
)
1846 : CommandObjectParsed(interpreter
, "type category enable",
1847 "Enable a category as a source of formatters.",
1850 CommandArgumentEntry type_arg
;
1851 CommandArgumentData type_style_arg
;
1853 type_style_arg
.arg_type
= eArgTypeName
;
1854 type_style_arg
.arg_repetition
= eArgRepeatPlus
;
1856 type_arg
.push_back(type_style_arg
);
1858 m_arguments
.push_back(type_arg
);
1861 ~CommandObjectTypeCategoryEnable() override
= default;
1864 bool DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1865 const size_t argc
= command
.GetArgumentCount();
1867 if (argc
< 1 && m_options
.m_language
== lldb::eLanguageTypeUnknown
) {
1868 result
.AppendErrorWithFormat("%s takes arguments and/or a language",
1869 m_cmd_name
.c_str());
1870 result
.SetStatus(eReturnStatusFailed
);
1874 if (argc
== 1 && strcmp(command
.GetArgumentAtIndex(0), "*") == 0) {
1875 DataVisualization::Categories::EnableStar();
1876 } else if (argc
> 0) {
1877 for (int i
= argc
- 1; i
>= 0; i
--) {
1878 const char *typeA
= command
.GetArgumentAtIndex(i
);
1879 ConstString
typeCS(typeA
);
1882 result
.AppendError("empty category name not allowed");
1883 result
.SetStatus(eReturnStatusFailed
);
1886 DataVisualization::Categories::Enable(typeCS
);
1887 lldb::TypeCategoryImplSP cate
;
1888 if (DataVisualization::Categories::GetCategory(typeCS
, cate
) && cate
) {
1889 if (cate
->GetCount() == 0) {
1890 result
.AppendWarning("empty category enabled (typo?)");
1896 if (m_options
.m_language
!= lldb::eLanguageTypeUnknown
)
1897 DataVisualization::Categories::Enable(m_options
.m_language
);
1899 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1900 return result
.Succeeded();
1904 // CommandObjectTypeCategoryDelete
1906 class CommandObjectTypeCategoryDelete
: public CommandObjectParsed
{
1908 CommandObjectTypeCategoryDelete(CommandInterpreter
&interpreter
)
1909 : CommandObjectParsed(interpreter
, "type category delete",
1910 "Delete a category and all associated formatters.",
1912 CommandArgumentEntry type_arg
;
1913 CommandArgumentData type_style_arg
;
1915 type_style_arg
.arg_type
= eArgTypeName
;
1916 type_style_arg
.arg_repetition
= eArgRepeatPlus
;
1918 type_arg
.push_back(type_style_arg
);
1920 m_arguments
.push_back(type_arg
);
1923 ~CommandObjectTypeCategoryDelete() override
= default;
1926 bool DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1927 const size_t argc
= command
.GetArgumentCount();
1930 result
.AppendErrorWithFormat("%s takes 1 or more arg.\n",
1931 m_cmd_name
.c_str());
1932 result
.SetStatus(eReturnStatusFailed
);
1936 bool success
= true;
1938 // the order is not relevant here
1939 for (int i
= argc
- 1; i
>= 0; i
--) {
1940 const char *typeA
= command
.GetArgumentAtIndex(i
);
1941 ConstString
typeCS(typeA
);
1944 result
.AppendError("empty category name not allowed");
1945 result
.SetStatus(eReturnStatusFailed
);
1948 if (!DataVisualization::Categories::Delete(typeCS
))
1949 success
= false; // keep deleting even if we hit an error
1952 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1953 return result
.Succeeded();
1955 result
.AppendError("cannot delete one or more categories\n");
1956 result
.SetStatus(eReturnStatusFailed
);
1962 // CommandObjectTypeCategoryDisable
1963 #define LLDB_OPTIONS_type_category_disable
1964 #include "CommandOptions.inc"
1966 class CommandObjectTypeCategoryDisable
: public CommandObjectParsed
{
1967 class CommandOptions
: public Options
{
1969 CommandOptions() : Options() {}
1971 ~CommandOptions() override
= default;
1973 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1974 ExecutionContext
*execution_context
) override
{
1976 const int short_option
= m_getopt_table
[option_idx
].val
;
1978 switch (short_option
) {
1980 if (!option_arg
.empty()) {
1981 m_language
= Language::GetLanguageTypeFromString(option_arg
);
1982 if (m_language
== lldb::eLanguageTypeUnknown
)
1983 error
.SetErrorStringWithFormat("unrecognized language '%s'",
1984 option_arg
.str().c_str());
1988 llvm_unreachable("Unimplemented option");
1994 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1995 m_language
= lldb::eLanguageTypeUnknown
;
1998 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1999 return llvm::makeArrayRef(g_type_category_disable_options
);
2002 // Instance variables to hold the values for command options.
2004 lldb::LanguageType m_language
;
2007 CommandOptions m_options
;
2009 Options
*GetOptions() override
{ return &m_options
; }
2012 CommandObjectTypeCategoryDisable(CommandInterpreter
&interpreter
)
2013 : CommandObjectParsed(interpreter
, "type category disable",
2014 "Disable a category as a source of formatters.",
2017 CommandArgumentEntry type_arg
;
2018 CommandArgumentData type_style_arg
;
2020 type_style_arg
.arg_type
= eArgTypeName
;
2021 type_style_arg
.arg_repetition
= eArgRepeatPlus
;
2023 type_arg
.push_back(type_style_arg
);
2025 m_arguments
.push_back(type_arg
);
2028 ~CommandObjectTypeCategoryDisable() override
= default;
2031 bool DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
2032 const size_t argc
= command
.GetArgumentCount();
2034 if (argc
< 1 && m_options
.m_language
== lldb::eLanguageTypeUnknown
) {
2035 result
.AppendErrorWithFormat("%s takes arguments and/or a language",
2036 m_cmd_name
.c_str());
2037 result
.SetStatus(eReturnStatusFailed
);
2041 if (argc
== 1 && strcmp(command
.GetArgumentAtIndex(0), "*") == 0) {
2042 DataVisualization::Categories::DisableStar();
2043 } else if (argc
> 0) {
2044 // the order is not relevant here
2045 for (int i
= argc
- 1; i
>= 0; i
--) {
2046 const char *typeA
= command
.GetArgumentAtIndex(i
);
2047 ConstString
typeCS(typeA
);
2050 result
.AppendError("empty category name not allowed");
2051 result
.SetStatus(eReturnStatusFailed
);
2054 DataVisualization::Categories::Disable(typeCS
);
2058 if (m_options
.m_language
!= lldb::eLanguageTypeUnknown
)
2059 DataVisualization::Categories::Disable(m_options
.m_language
);
2061 result
.SetStatus(eReturnStatusSuccessFinishResult
);
2062 return result
.Succeeded();
2066 // CommandObjectTypeCategoryList
2068 class CommandObjectTypeCategoryList
: public CommandObjectParsed
{
2070 CommandObjectTypeCategoryList(CommandInterpreter
&interpreter
)
2071 : CommandObjectParsed(interpreter
, "type category list",
2072 "Provide a list of all existing categories.",
2074 CommandArgumentEntry type_arg
;
2075 CommandArgumentData type_style_arg
;
2077 type_style_arg
.arg_type
= eArgTypeName
;
2078 type_style_arg
.arg_repetition
= eArgRepeatOptional
;
2080 type_arg
.push_back(type_style_arg
);
2082 m_arguments
.push_back(type_arg
);
2085 ~CommandObjectTypeCategoryList() override
= default;
2088 bool DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
2089 const size_t argc
= command
.GetArgumentCount();
2091 std::unique_ptr
<RegularExpression
> regex
;
2094 const char *arg
= command
.GetArgumentAtIndex(0);
2095 regex
.reset(new RegularExpression(llvm::StringRef::withNullAsEmpty(arg
)));
2096 if (!regex
->IsValid()) {
2097 result
.AppendErrorWithFormat(
2098 "syntax error in category regular expression '%s'", arg
);
2099 result
.SetStatus(eReturnStatusFailed
);
2102 } else if (argc
!= 0) {
2103 result
.AppendErrorWithFormat("%s takes 0 or one arg.\n",
2104 m_cmd_name
.c_str());
2105 result
.SetStatus(eReturnStatusFailed
);
2109 DataVisualization::Categories::ForEach(
2110 [®ex
, &result
](const lldb::TypeCategoryImplSP
&category_sp
) -> bool {
2113 if (regex
->GetText() == category_sp
->GetName()) {
2115 } else if (regex
->Execute(llvm::StringRef::withNullAsEmpty(
2116 category_sp
->GetName()))) {
2124 result
.GetOutputStream().Printf(
2125 "Category: %s\n", category_sp
->GetDescription().c_str());
2130 result
.SetStatus(eReturnStatusSuccessFinishResult
);
2131 return result
.Succeeded();
2135 // CommandObjectTypeFilterList
2137 class CommandObjectTypeFilterList
2138 : public CommandObjectTypeFormatterList
<TypeFilterImpl
> {
2140 CommandObjectTypeFilterList(CommandInterpreter
&interpreter
)
2141 : CommandObjectTypeFormatterList(interpreter
, "type filter list",
2142 "Show a list of current filters.") {}
2145 #if LLDB_ENABLE_PYTHON
2147 // CommandObjectTypeSynthList
2149 class CommandObjectTypeSynthList
2150 : public CommandObjectTypeFormatterList
<SyntheticChildren
> {
2152 CommandObjectTypeSynthList(CommandInterpreter
&interpreter
)
2153 : CommandObjectTypeFormatterList(
2154 interpreter
, "type synthetic list",
2155 "Show a list of current synthetic providers.") {}
2160 // CommandObjectTypeFilterDelete
2162 class CommandObjectTypeFilterDelete
: public CommandObjectTypeFormatterDelete
{
2164 CommandObjectTypeFilterDelete(CommandInterpreter
&interpreter
)
2165 : CommandObjectTypeFormatterDelete(
2167 eFormatCategoryItemFilter
| eFormatCategoryItemRegexFilter
,
2168 "type filter delete", "Delete an existing filter for a type.") {}
2170 ~CommandObjectTypeFilterDelete() override
= default;
2173 #if LLDB_ENABLE_PYTHON
2175 // CommandObjectTypeSynthDelete
2177 class CommandObjectTypeSynthDelete
: public CommandObjectTypeFormatterDelete
{
2179 CommandObjectTypeSynthDelete(CommandInterpreter
&interpreter
)
2180 : CommandObjectTypeFormatterDelete(
2182 eFormatCategoryItemSynth
| eFormatCategoryItemRegexSynth
,
2183 "type synthetic delete",
2184 "Delete an existing synthetic provider for a type.") {}
2186 ~CommandObjectTypeSynthDelete() override
= default;
2191 // CommandObjectTypeFilterClear
2193 class CommandObjectTypeFilterClear
: public CommandObjectTypeFormatterClear
{
2195 CommandObjectTypeFilterClear(CommandInterpreter
&interpreter
)
2196 : CommandObjectTypeFormatterClear(
2198 eFormatCategoryItemFilter
| eFormatCategoryItemRegexFilter
,
2199 "type filter clear", "Delete all existing filter.") {}
2202 #if LLDB_ENABLE_PYTHON
2203 // CommandObjectTypeSynthClear
2205 class CommandObjectTypeSynthClear
: public CommandObjectTypeFormatterClear
{
2207 CommandObjectTypeSynthClear(CommandInterpreter
&interpreter
)
2208 : CommandObjectTypeFormatterClear(
2210 eFormatCategoryItemSynth
| eFormatCategoryItemRegexSynth
,
2211 "type synthetic clear",
2212 "Delete all existing synthetic providers.") {}
2215 bool CommandObjectTypeSynthAdd::Execute_HandwritePython(
2216 Args
&command
, CommandReturnObject
&result
) {
2217 SynthAddOptions
*options
= new SynthAddOptions(
2218 m_options
.m_skip_pointers
, m_options
.m_skip_references
,
2219 m_options
.m_cascade
, m_options
.m_regex
, m_options
.m_category
);
2221 for (auto &entry
: command
.entries()) {
2222 if (entry
.ref().empty()) {
2223 result
.AppendError("empty typenames not allowed");
2224 result
.SetStatus(eReturnStatusFailed
);
2228 options
->m_target_types
<< entry
.ref();
2231 m_interpreter
.GetPythonCommandsFromIOHandler(
2233 *this, // IOHandlerDelegate
2234 options
); // Baton for the "io_handler" that will be passed back into our
2235 // IOHandlerDelegate functions
2236 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2237 return result
.Succeeded();
2240 bool CommandObjectTypeSynthAdd::Execute_PythonClass(
2241 Args
&command
, CommandReturnObject
&result
) {
2242 const size_t argc
= command
.GetArgumentCount();
2245 result
.AppendErrorWithFormat("%s takes one or more args.\n",
2246 m_cmd_name
.c_str());
2247 result
.SetStatus(eReturnStatusFailed
);
2251 if (m_options
.m_class_name
.empty() && !m_options
.m_input_python
) {
2252 result
.AppendErrorWithFormat("%s needs either a Python class name or -P to "
2253 "directly input Python code.\n",
2254 m_cmd_name
.c_str());
2255 result
.SetStatus(eReturnStatusFailed
);
2259 SyntheticChildrenSP entry
;
2261 ScriptedSyntheticChildren
*impl
= new ScriptedSyntheticChildren(
2262 SyntheticChildren::Flags()
2263 .SetCascades(m_options
.m_cascade
)
2264 .SetSkipPointers(m_options
.m_skip_pointers
)
2265 .SetSkipReferences(m_options
.m_skip_references
),
2266 m_options
.m_class_name
.c_str());
2270 ScriptInterpreter
*interpreter
= GetDebugger().GetScriptInterpreter();
2273 !interpreter
->CheckObjectExists(impl
->GetPythonClassName()))
2274 result
.AppendWarning("The provided class does not exist - please define it "
2275 "before attempting to use this synthetic provider");
2277 // now I have a valid provider, let's add it to every type
2279 lldb::TypeCategoryImplSP category
;
2280 DataVisualization::Categories::GetCategory(
2281 ConstString(m_options
.m_category
.c_str()), category
);
2285 for (auto &arg_entry
: command
.entries()) {
2286 if (arg_entry
.ref().empty()) {
2287 result
.AppendError("empty typenames not allowed");
2288 result
.SetStatus(eReturnStatusFailed
);
2292 ConstString
typeCS(arg_entry
.ref());
2293 if (!AddSynth(typeCS
, entry
,
2294 m_options
.m_regex
? eRegexSynth
: eRegularSynth
,
2295 m_options
.m_category
, &error
)) {
2296 result
.AppendError(error
.AsCString());
2297 result
.SetStatus(eReturnStatusFailed
);
2302 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2303 return result
.Succeeded();
2306 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd(
2307 CommandInterpreter
&interpreter
)
2308 : CommandObjectParsed(interpreter
, "type synthetic add",
2309 "Add a new synthetic provider for a type.", nullptr),
2310 IOHandlerDelegateMultiline("DONE"), m_options() {
2311 CommandArgumentEntry type_arg
;
2312 CommandArgumentData type_style_arg
;
2314 type_style_arg
.arg_type
= eArgTypeName
;
2315 type_style_arg
.arg_repetition
= eArgRepeatPlus
;
2317 type_arg
.push_back(type_style_arg
);
2319 m_arguments
.push_back(type_arg
);
2322 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name
,
2323 SyntheticChildrenSP entry
,
2324 SynthFormatType type
,
2325 std::string category_name
,
2327 lldb::TypeCategoryImplSP category
;
2328 DataVisualization::Categories::GetCategory(ConstString(category_name
.c_str()),
2331 if (type
== eRegularSynth
) {
2332 if (FixArrayTypeNameWithRegex(type_name
))
2336 if (category
->AnyMatches(
2337 type_name
, eFormatCategoryItemFilter
| eFormatCategoryItemRegexFilter
,
2340 error
->SetErrorStringWithFormat("cannot add synthetic for type %s when "
2341 "filter is defined in same category!",
2342 type_name
.AsCString());
2346 if (type
== eRegexSynth
) {
2347 RegularExpression
typeRX(type_name
.GetStringRef());
2348 if (!typeRX
.IsValid()) {
2350 error
->SetErrorString(
2351 "regex format error (maybe this is not really a regex?)");
2355 category
->GetRegexTypeSyntheticsContainer()->Delete(type_name
);
2356 category
->GetRegexTypeSyntheticsContainer()->Add(std::move(typeRX
), entry
);
2360 category
->GetTypeSyntheticsContainer()->Add(std::move(type_name
), entry
);
2366 #define LLDB_OPTIONS_type_filter_add
2367 #include "CommandOptions.inc"
2369 class CommandObjectTypeFilterAdd
: public CommandObjectParsed
{
2371 class CommandOptions
: public Options
{
2372 typedef std::vector
<std::string
> option_vector
;
2375 CommandOptions() : Options() {}
2377 ~CommandOptions() override
= default;
2379 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
2380 ExecutionContext
*execution_context
) override
{
2382 const int short_option
= m_getopt_table
[option_idx
].val
;
2385 switch (short_option
) {
2387 m_cascade
= OptionArgParser::ToBoolean(option_arg
, true, &success
);
2389 error
.SetErrorStringWithFormat("invalid value for cascade: %s",
2390 option_arg
.str().c_str());
2393 m_expr_paths
.push_back(option_arg
);
2394 has_child_list
= true;
2397 m_skip_pointers
= true;
2400 m_skip_references
= true;
2403 m_category
= std::string(option_arg
);
2409 llvm_unreachable("Unimplemented option");
2415 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2417 m_skip_pointers
= false;
2418 m_skip_references
= false;
2419 m_category
= "default";
2420 m_expr_paths
.clear();
2421 has_child_list
= false;
2425 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2426 return llvm::makeArrayRef(g_type_filter_add_options
);
2429 // Instance variables to hold the values for command options.
2432 bool m_skip_references
;
2433 bool m_skip_pointers
;
2434 bool m_input_python
;
2435 option_vector m_expr_paths
;
2436 std::string m_category
;
2437 bool has_child_list
;
2440 typedef option_vector::iterator ExpressionPathsIterator
;
2443 CommandOptions m_options
;
2445 Options
*GetOptions() override
{ return &m_options
; }
2447 enum FilterFormatType
{ eRegularFilter
, eRegexFilter
};
2449 bool AddFilter(ConstString type_name
, TypeFilterImplSP entry
,
2450 FilterFormatType type
, std::string category_name
,
2452 lldb::TypeCategoryImplSP category
;
2453 DataVisualization::Categories::GetCategory(
2454 ConstString(category_name
.c_str()), category
);
2456 if (type
== eRegularFilter
) {
2457 if (FixArrayTypeNameWithRegex(type_name
))
2458 type
= eRegexFilter
;
2461 if (category
->AnyMatches(
2462 type_name
, eFormatCategoryItemSynth
| eFormatCategoryItemRegexSynth
,
2465 error
->SetErrorStringWithFormat("cannot add filter for type %s when "
2466 "synthetic is defined in same "
2468 type_name
.AsCString());
2472 if (type
== eRegexFilter
) {
2473 RegularExpression
typeRX(type_name
.GetStringRef());
2474 if (!typeRX
.IsValid()) {
2476 error
->SetErrorString(
2477 "regex format error (maybe this is not really a regex?)");
2481 category
->GetRegexTypeFiltersContainer()->Delete(type_name
);
2482 category
->GetRegexTypeFiltersContainer()->Add(std::move(typeRX
), entry
);
2486 category
->GetTypeFiltersContainer()->Add(std::move(type_name
), entry
);
2492 CommandObjectTypeFilterAdd(CommandInterpreter
&interpreter
)
2493 : CommandObjectParsed(interpreter
, "type filter add",
2494 "Add a new filter for a type.", nullptr),
2496 CommandArgumentEntry type_arg
;
2497 CommandArgumentData type_style_arg
;
2499 type_style_arg
.arg_type
= eArgTypeName
;
2500 type_style_arg
.arg_repetition
= eArgRepeatPlus
;
2502 type_arg
.push_back(type_style_arg
);
2504 m_arguments
.push_back(type_arg
);
2508 The following examples of 'type filter add' refer to this code snippet for context:
2523 Adding a simple filter:
2525 (lldb) type filter add --child a --child g Foo
2526 (lldb) frame variable my_foo
2529 "Produces output where only a and g are displayed. Other children of my_foo \
2530 (b, c, d, e, f, h and i) are available by asking for them explicitly:"
2533 (lldb) frame variable my_foo.b my_foo.c my_foo.i
2536 "The formatting option --raw on frame variable bypasses the filter, showing \
2537 all children of my_foo as if no filter was defined:"
2540 (lldb) frame variable my_foo --raw)");
2543 ~CommandObjectTypeFilterAdd() override
= default;
2546 bool DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
2547 const size_t argc
= command
.GetArgumentCount();
2550 result
.AppendErrorWithFormat("%s takes one or more args.\n",
2551 m_cmd_name
.c_str());
2552 result
.SetStatus(eReturnStatusFailed
);
2556 if (m_options
.m_expr_paths
.empty()) {
2557 result
.AppendErrorWithFormat("%s needs one or more children.\n",
2558 m_cmd_name
.c_str());
2559 result
.SetStatus(eReturnStatusFailed
);
2563 TypeFilterImplSP
entry(new TypeFilterImpl(
2564 SyntheticChildren::Flags()
2565 .SetCascades(m_options
.m_cascade
)
2566 .SetSkipPointers(m_options
.m_skip_pointers
)
2567 .SetSkipReferences(m_options
.m_skip_references
)));
2569 // go through the expression paths
2570 CommandOptions::ExpressionPathsIterator begin
,
2571 end
= m_options
.m_expr_paths
.end();
2573 for (begin
= m_options
.m_expr_paths
.begin(); begin
!= end
; begin
++)
2574 entry
->AddExpressionPath(*begin
);
2576 // now I have a valid provider, let's add it to every type
2578 lldb::TypeCategoryImplSP category
;
2579 DataVisualization::Categories::GetCategory(
2580 ConstString(m_options
.m_category
.c_str()), category
);
2584 WarnOnPotentialUnquotedUnsignedType(command
, result
);
2586 for (auto &arg_entry
: command
.entries()) {
2587 if (arg_entry
.ref().empty()) {
2588 result
.AppendError("empty typenames not allowed");
2589 result
.SetStatus(eReturnStatusFailed
);
2593 ConstString
typeCS(arg_entry
.ref());
2594 if (!AddFilter(typeCS
, entry
,
2595 m_options
.m_regex
? eRegexFilter
: eRegularFilter
,
2596 m_options
.m_category
, &error
)) {
2597 result
.AppendError(error
.AsCString());
2598 result
.SetStatus(eReturnStatusFailed
);
2603 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2604 return result
.Succeeded();
2609 #define LLDB_OPTIONS_type_lookup
2610 #include "CommandOptions.inc"
2612 class CommandObjectTypeLookup
: public CommandObjectRaw
{
2614 // this function is allowed to do a more aggressive job at guessing languages
2615 // than the expression parser is comfortable with - so leave the original
2616 // call alone and add one that is specific to type lookup
2617 lldb::LanguageType
GuessLanguage(StackFrame
*frame
) {
2618 lldb::LanguageType lang_type
= lldb::eLanguageTypeUnknown
;
2623 lang_type
= frame
->GuessLanguage();
2624 if (lang_type
!= lldb::eLanguageTypeUnknown
)
2627 Symbol
*s
= frame
->GetSymbolContext(eSymbolContextSymbol
).symbol
;
2629 lang_type
= s
->GetMangled().GuessLanguage();
2634 class CommandOptions
: public OptionGroup
{
2637 : OptionGroup(), m_show_help(false), m_language(eLanguageTypeUnknown
) {}
2639 ~CommandOptions() override
= default;
2641 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2642 return llvm::makeArrayRef(g_type_lookup_options
);
2645 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_value
,
2646 ExecutionContext
*execution_context
) override
{
2649 const int short_option
= g_type_lookup_options
[option_idx
].short_option
;
2651 switch (short_option
) {
2657 m_language
= Language::GetLanguageTypeFromString(option_value
);
2661 llvm_unreachable("Unimplemented option");
2667 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2668 m_show_help
= false;
2669 m_language
= eLanguageTypeUnknown
;
2672 // Options table: Required for subclasses of Options.
2675 lldb::LanguageType m_language
;
2678 OptionGroupOptions m_option_group
;
2679 CommandOptions m_command_options
;
2682 CommandObjectTypeLookup(CommandInterpreter
&interpreter
)
2683 : CommandObjectRaw(interpreter
, "type lookup",
2684 "Lookup types and declarations in the current target, "
2685 "following language-specific naming conventions.",
2686 "type lookup <type-specifier>",
2687 eCommandRequiresTarget
),
2688 m_option_group(), m_command_options() {
2689 m_option_group
.Append(&m_command_options
);
2690 m_option_group
.Finalize();
2693 ~CommandObjectTypeLookup() override
= default;
2695 Options
*GetOptions() override
{ return &m_option_group
; }
2697 llvm::StringRef
GetHelpLong() override
{
2698 if (!m_cmd_help_long
.empty())
2699 return m_cmd_help_long
;
2701 StreamString stream
;
2702 Language::ForEach([&](Language
*lang
) {
2703 if (const char *help
= lang
->GetLanguageSpecificTypeLookupHelp())
2704 stream
.Printf("%s\n", help
);
2708 m_cmd_help_long
= stream
.GetString();
2709 return m_cmd_help_long
;
2712 bool DoExecute(llvm::StringRef raw_command_line
,
2713 CommandReturnObject
&result
) override
{
2714 if (raw_command_line
.empty()) {
2716 "type lookup cannot be invoked without a type name as argument");
2720 auto exe_ctx
= GetCommandInterpreter().GetExecutionContext();
2721 m_option_group
.NotifyOptionParsingStarting(&exe_ctx
);
2723 OptionsWithRaw
args(raw_command_line
);
2724 const char *name_of_type
= args
.GetRawPart().c_str();
2727 if (!ParseOptionsAndNotify(args
.GetArgs(), result
, m_option_group
,
2731 ExecutionContextScope
*best_scope
= exe_ctx
.GetBestExecutionContextScope();
2733 bool any_found
= false;
2735 std::vector
<Language
*> languages
;
2737 bool is_global_search
= false;
2738 LanguageType guessed_language
= lldb::eLanguageTypeUnknown
;
2740 if ((is_global_search
=
2741 (m_command_options
.m_language
== eLanguageTypeUnknown
))) {
2742 Language::ForEach([&](Language
*lang
) {
2743 languages
.push_back(lang
);
2747 languages
.push_back(Language::FindPlugin(m_command_options
.m_language
));
2750 // This is not the most efficient way to do this, but we support very few
2751 // languages so the cost of the sort is going to be dwarfed by the actual
2753 if (StackFrame
*frame
= m_exe_ctx
.GetFramePtr()) {
2754 guessed_language
= GuessLanguage(frame
);
2755 if (guessed_language
!= eLanguageTypeUnknown
) {
2757 languages
.begin(), languages
.end(),
2758 [guessed_language
](Language
*lang1
, Language
*lang2
) -> bool {
2759 if (!lang1
|| !lang2
)
2761 LanguageType lt1
= lang1
->GetLanguageType();
2762 LanguageType lt2
= lang2
->GetLanguageType();
2763 if (lt1
== guessed_language
)
2764 return true; // make the selected frame's language come first
2765 if (lt2
== guessed_language
)
2766 return false; // make the selected frame's language come first
2767 return (lt1
< lt2
); // normal comparison otherwise
2772 bool is_first_language
= true;
2774 for (Language
*language
: languages
) {
2778 if (auto scavenger
= language
->GetTypeScavenger()) {
2779 Language::TypeScavenger::ResultSet search_results
;
2780 if (scavenger
->Find(best_scope
, name_of_type
, search_results
) > 0) {
2781 for (const auto &search_result
: search_results
) {
2782 if (search_result
&& search_result
->IsValid()) {
2784 search_result
->DumpToStream(result
.GetOutputStream(),
2785 this->m_command_options
.m_show_help
);
2790 // this is "type lookup SomeName" and we did find a match, so get out
2791 if (any_found
&& is_global_search
)
2793 else if (is_first_language
&& is_global_search
&&
2794 guessed_language
!= lldb::eLanguageTypeUnknown
) {
2795 is_first_language
= false;
2796 result
.GetOutputStream().Printf(
2797 "no type was found in the current language %s matching '%s'; "
2798 "performing a global search across all languages\n",
2799 Language::GetNameForLanguageType(guessed_language
), name_of_type
);
2804 result
.AppendMessageWithFormat("no type was found matching '%s'\n",
2807 result
.SetStatus(any_found
? lldb::eReturnStatusSuccessFinishResult
2808 : lldb::eReturnStatusSuccessFinishNoResult
);
2813 template <typename FormatterType
>
2814 class CommandObjectFormatterInfo
: public CommandObjectRaw
{
2816 typedef std::function
<typename
FormatterType::SharedPointer(ValueObject
&)>
2818 CommandObjectFormatterInfo(CommandInterpreter
&interpreter
,
2819 const char *formatter_name
,
2820 DiscoveryFunction discovery_func
)
2821 : CommandObjectRaw(interpreter
, "", "", "", eCommandRequiresFrame
),
2822 m_formatter_name(formatter_name
? formatter_name
: ""),
2823 m_discovery_function(discovery_func
) {
2825 name
.Printf("type %s info", formatter_name
);
2826 SetCommandName(name
.GetString());
2828 help
.Printf("This command evaluates the provided expression and shows "
2829 "which %s is applied to the resulting value (if any).",
2831 SetHelp(help
.GetString());
2832 StreamString syntax
;
2833 syntax
.Printf("type %s info <expr>", formatter_name
);
2834 SetSyntax(syntax
.GetString());
2837 ~CommandObjectFormatterInfo() override
= default;
2840 bool DoExecute(llvm::StringRef command
,
2841 CommandReturnObject
&result
) override
{
2842 TargetSP target_sp
= GetDebugger().GetSelectedTarget();
2843 Thread
*thread
= GetDefaultThread();
2845 result
.AppendError("no default thread");
2846 result
.SetStatus(lldb::eReturnStatusFailed
);
2850 StackFrameSP frame_sp
= thread
->GetSelectedFrame();
2851 ValueObjectSP result_valobj_sp
;
2852 EvaluateExpressionOptions options
;
2853 lldb::ExpressionResults expr_result
= target_sp
->EvaluateExpression(
2854 command
, frame_sp
.get(), result_valobj_sp
, options
);
2855 if (expr_result
== eExpressionCompleted
&& result_valobj_sp
) {
2857 result_valobj_sp
->GetQualifiedRepresentationIfAvailable(
2858 target_sp
->GetPreferDynamicValue(),
2859 target_sp
->GetEnableSyntheticValue());
2860 typename
FormatterType::SharedPointer formatter_sp
=
2861 m_discovery_function(*result_valobj_sp
);
2863 std::string
description(formatter_sp
->GetDescription());
2864 result
.GetOutputStream()
2865 << m_formatter_name
<< " applied to ("
2866 << result_valobj_sp
->GetDisplayTypeName().AsCString("<unknown>")
2867 << ") " << command
<< " is: " << description
<< "\n";
2868 result
.SetStatus(lldb::eReturnStatusSuccessFinishResult
);
2870 result
.GetOutputStream()
2871 << "no " << m_formatter_name
<< " applies to ("
2872 << result_valobj_sp
->GetDisplayTypeName().AsCString("<unknown>")
2873 << ") " << command
<< "\n";
2874 result
.SetStatus(lldb::eReturnStatusSuccessFinishNoResult
);
2878 result
.AppendError("failed to evaluate expression");
2879 result
.SetStatus(lldb::eReturnStatusFailed
);
2885 std::string m_formatter_name
;
2886 DiscoveryFunction m_discovery_function
;
2889 class CommandObjectTypeFormat
: public CommandObjectMultiword
{
2891 CommandObjectTypeFormat(CommandInterpreter
&interpreter
)
2892 : CommandObjectMultiword(
2893 interpreter
, "type format",
2894 "Commands for customizing value display formats.",
2895 "type format [<sub-command-options>] ") {
2897 "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter
)));
2898 LoadSubCommand("clear", CommandObjectSP(
2899 new CommandObjectTypeFormatClear(interpreter
)));
2900 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete(
2903 "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter
)));
2905 "info", CommandObjectSP(new CommandObjectFormatterInfo
<TypeFormatImpl
>(
2906 interpreter
, "format",
2907 [](ValueObject
&valobj
) -> TypeFormatImpl::SharedPointer
{
2908 return valobj
.GetValueFormat();
2912 ~CommandObjectTypeFormat() override
= default;
2915 #if LLDB_ENABLE_PYTHON
2917 class CommandObjectTypeSynth
: public CommandObjectMultiword
{
2919 CommandObjectTypeSynth(CommandInterpreter
&interpreter
)
2920 : CommandObjectMultiword(
2921 interpreter
, "type synthetic",
2922 "Commands for operating on synthetic type representations.",
2923 "type synthetic [<sub-command-options>] ") {
2924 LoadSubCommand("add",
2925 CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter
)));
2927 "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter
)));
2928 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete(
2931 "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter
)));
2934 CommandObjectSP(new CommandObjectFormatterInfo
<SyntheticChildren
>(
2935 interpreter
, "synthetic",
2936 [](ValueObject
&valobj
) -> SyntheticChildren::SharedPointer
{
2937 return valobj
.GetSyntheticChildren();
2941 ~CommandObjectTypeSynth() override
= default;
2946 class CommandObjectTypeFilter
: public CommandObjectMultiword
{
2948 CommandObjectTypeFilter(CommandInterpreter
&interpreter
)
2949 : CommandObjectMultiword(interpreter
, "type filter",
2950 "Commands for operating on type filters.",
2951 "type synthetic [<sub-command-options>] ") {
2953 "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter
)));
2954 LoadSubCommand("clear", CommandObjectSP(
2955 new CommandObjectTypeFilterClear(interpreter
)));
2956 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete(
2959 "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter
)));
2962 ~CommandObjectTypeFilter() override
= default;
2965 class CommandObjectTypeCategory
: public CommandObjectMultiword
{
2967 CommandObjectTypeCategory(CommandInterpreter
&interpreter
)
2968 : CommandObjectMultiword(interpreter
, "type category",
2969 "Commands for operating on type categories.",
2970 "type category [<sub-command-options>] ") {
2973 CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter
)));
2976 CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter
)));
2979 CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter
)));
2982 CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter
)));
2983 LoadSubCommand("list", CommandObjectSP(
2984 new CommandObjectTypeCategoryList(interpreter
)));
2987 ~CommandObjectTypeCategory() override
= default;
2990 class CommandObjectTypeSummary
: public CommandObjectMultiword
{
2992 CommandObjectTypeSummary(CommandInterpreter
&interpreter
)
2993 : CommandObjectMultiword(
2994 interpreter
, "type summary",
2995 "Commands for editing variable summary display options.",
2996 "type summary [<sub-command-options>] ") {
2998 "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter
)));
2999 LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear(
3001 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete(
3004 "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter
)));
3006 "info", CommandObjectSP(new CommandObjectFormatterInfo
<TypeSummaryImpl
>(
3007 interpreter
, "summary",
3008 [](ValueObject
&valobj
) -> TypeSummaryImpl::SharedPointer
{
3009 return valobj
.GetSummaryFormat();
3013 ~CommandObjectTypeSummary() override
= default;
3016 // CommandObjectType
3018 CommandObjectType::CommandObjectType(CommandInterpreter
&interpreter
)
3019 : CommandObjectMultiword(interpreter
, "type",
3020 "Commands for operating on the type system.",
3021 "type [<sub-command-options>]") {
3022 LoadSubCommand("category",
3023 CommandObjectSP(new CommandObjectTypeCategory(interpreter
)));
3024 LoadSubCommand("filter",
3025 CommandObjectSP(new CommandObjectTypeFilter(interpreter
)));
3026 LoadSubCommand("format",
3027 CommandObjectSP(new CommandObjectTypeFormat(interpreter
)));
3028 LoadSubCommand("summary",
3029 CommandObjectSP(new CommandObjectTypeSummary(interpreter
)));
3030 #if LLDB_ENABLE_PYTHON
3031 LoadSubCommand("synthetic",
3032 CommandObjectSP(new CommandObjectTypeSynth(interpreter
)));
3034 LoadSubCommand("lookup",
3035 CommandObjectSP(new CommandObjectTypeLookup(interpreter
)));
3038 CommandObjectType::~CommandObjectType() = default;