LLDB mainline
CommandObjectType.cpp
Go to the documentation of this file.
1//===-- CommandObjectType.cpp ---------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "CommandObjectType.h"
10
11#include "lldb/Core/Debugger.h"
12#include "lldb/Core/IOHandler.h"
15#include "lldb/Host/Config.h"
27#include "lldb/Symbol/Symbol.h"
30#include "lldb/Target/Target.h"
31#include "lldb/Target/Thread.h"
35
36#include "llvm/ADT/STLExtras.h"
37
38#include <algorithm>
39#include <functional>
40#include <memory>
41
42using namespace lldb;
43using namespace lldb_private;
44
46public:
51 std::string m_category;
52
54 FormatterMatchType match_type, ConstString name,
55 std::string catg)
56 : m_flags(flags), m_match_type(match_type), m_name(name),
57 m_category(catg) {}
58
59 typedef std::shared_ptr<ScriptAddOptions> SharedPointer;
60};
61
63public:
69 std::string m_category;
70
71 SynthAddOptions(bool sptr, bool sref, bool casc,
72 FormatterMatchType match_type, std::string catg)
73 : m_skip_pointers(sptr), m_skip_references(sref), m_cascade(casc),
74 m_match_type(match_type), m_category(catg) {}
75
76 typedef std::shared_ptr<SynthAddOptions> SharedPointer;
77};
78
80 CommandReturnObject &result) {
81 if (command.empty())
82 return false;
83
84 for (auto entry : llvm::enumerate(command.entries().drop_back())) {
85 if (entry.value().ref() != "unsigned")
86 continue;
87 auto next = command.entries()[entry.index() + 1].ref();
88 if (next == "int" || next == "short" || next == "char" || next == "long") {
90 "unsigned %s being treated as two types. if you meant the combined "
91 "type "
92 "name use quotes, as in \"unsigned %s\"\n",
93 next.str().c_str(), next.str().c_str());
94 return true;
95 }
96 }
97 return false;
98}
99
100const char *FormatCategoryToString(FormatCategoryItem item, bool long_name) {
101 switch (item) {
103 return "summary";
105 return "filter";
107 if (long_name)
108 return "synthetic child provider";
109 return "synthetic";
111 return "format";
112 }
113 llvm_unreachable("Fully covered switch above!");
114}
115
116#define LLDB_OPTIONS_type_summary_add
117#include "CommandOptions.inc"
118
121private:
122 class CommandOptions : public Options {
123 public:
125
126 ~CommandOptions() override = default;
127
128 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
129 ExecutionContext *execution_context) override;
130
131 void OptionParsingStarting(ExecutionContext *execution_context) override;
132
133 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
134 return llvm::ArrayRef(g_type_summary_add_options);
135 }
136
137 // Instance variables to hold the values for command options.
138
141 std::string m_format_string;
143 std::string m_python_script;
144 std::string m_python_function;
145 bool m_is_add_script = false;
146 std::string m_category;
147 };
148
150
151 Options *GetOptions() override { return &m_options; }
152
154
155 bool Execute_StringSummary(Args &command, CommandReturnObject &result);
156
157public:
159
160 ~CommandObjectTypeSummaryAdd() override = default;
161
162 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
163 static const char *g_summary_addreader_instructions =
164 "Enter your Python command(s). Type 'DONE' to end.\n"
165 "def function (valobj,internal_dict):\n"
166 " \"\"\"valobj: an SBValue which you want to provide a summary "
167 "for\n"
168 " internal_dict: an LLDB support object not to be used\"\"\"\n";
169
170 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
171 if (output_sp && interactive) {
172 output_sp->PutCString(g_summary_addreader_instructions);
173 output_sp->Flush();
174 }
175 }
176
178 std::string &data) override {
179 StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
180
181#if LLDB_ENABLE_PYTHON
183 if (interpreter) {
184 StringList lines;
185 lines.SplitIntoLines(data);
186 if (lines.GetSize() > 0) {
187 ScriptAddOptions *options_ptr =
188 ((ScriptAddOptions *)io_handler.GetUserData());
189 if (options_ptr) {
191 options_ptr); // this will ensure that we get rid of the pointer
192 // when going out of scope
193
195 if (interpreter) {
196 std::string funct_name_str;
197 if (interpreter->GenerateTypeScriptFunction(lines,
198 funct_name_str)) {
199 if (funct_name_str.empty()) {
200 error_sp->Printf("unable to obtain a valid function name from "
201 "the script interpreter.\n");
202 error_sp->Flush();
203 } else {
204 // now I have a valid function name, let's add this as script
205 // for every type in the list
206
207 TypeSummaryImplSP script_format;
208 script_format = std::make_shared<ScriptSummaryFormat>(
209 options->m_flags, funct_name_str.c_str(),
210 lines.CopyList(" ").c_str());
211
213
214 for (const std::string &type_name : options->m_target_types) {
215 AddSummary(ConstString(type_name), script_format,
216 options->m_match_type, options->m_category,
217 &error);
218 if (error.Fail()) {
219 error_sp->Printf("error: %s", error.AsCString());
220 error_sp->Flush();
221 }
222 }
223
224 if (options->m_name) {
226 options->m_name, script_format, &error);
227 if (error.Fail()) {
229 options->m_name, script_format, &error);
230 if (error.Fail()) {
231 error_sp->Printf("error: %s", error.AsCString());
232 error_sp->Flush();
233 }
234 } else {
235 error_sp->Printf("error: %s", error.AsCString());
236 error_sp->Flush();
237 }
238 } else {
239 if (error.AsCString()) {
240 error_sp->Printf("error: %s", error.AsCString());
241 error_sp->Flush();
242 }
243 }
244 }
245 } else {
246 error_sp->Printf("error: unable to generate a function.\n");
247 error_sp->Flush();
248 }
249 } else {
250 error_sp->Printf("error: no script interpreter.\n");
251 error_sp->Flush();
252 }
253 } else {
254 error_sp->Printf("error: internal synchronization information "
255 "missing or invalid.\n");
256 error_sp->Flush();
257 }
258 } else {
259 error_sp->Printf("error: empty function, didn't add python command.\n");
260 error_sp->Flush();
261 }
262 } else {
263 error_sp->Printf(
264 "error: script interpreter missing, didn't add python command.\n");
265 error_sp->Flush();
266 }
267#endif
268 io_handler.SetIsDone(true);
269 }
270
271 bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry,
272 FormatterMatchType match_type, std::string category,
273 Status *error = nullptr);
274
275 bool AddNamedSummary(ConstString summary_name, lldb::TypeSummaryImplSP entry,
276 Status *error = nullptr);
277
278protected:
279 void DoExecute(Args &command, CommandReturnObject &result) override;
280};
281
283 "Enter your Python command(s). Type 'DONE' to end.\n"
284 "You must define a Python class with these methods:\n"
285 " def __init__(self, valobj, internal_dict):\n"
286 " def num_children(self):\n"
287 " def get_child_at_index(self, index):\n"
288 " def get_child_index(self, name):\n"
289 " def update(self):\n"
290 " '''Optional'''\n"
291 "class synthProvider:\n";
292
293#define LLDB_OPTIONS_type_synth_add
294#include "CommandOptions.inc"
295
298private:
299 class CommandOptions : public Options {
300 public:
301 CommandOptions() = default;
302
303 ~CommandOptions() override = default;
304
305 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
306 ExecutionContext *execution_context) override {
308 const int short_option = m_getopt_table[option_idx].val;
309 bool success;
310
311 switch (short_option) {
312 case 'C':
313 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
314 if (!success)
316 "invalid value for cascade: %s", option_arg.str().c_str());
317 break;
318 case 'P':
319 handwrite_python = true;
320 break;
321 case 'l':
322 m_class_name = std::string(option_arg);
323 is_class_based = true;
324 break;
325 case 'p':
326 m_skip_pointers = true;
327 break;
328 case 'r':
329 m_skip_references = true;
330 break;
331 case 'w':
332 m_category = std::string(option_arg);
333 break;
334 case 'x':
337 "can't use --regex and --recognizer-function at the same time");
338 else
340 break;
341 case '\x01':
344 "can't use --regex and --recognizer-function at the same time");
345 else
347 break;
348 default:
349 llvm_unreachable("Unimplemented option");
350 }
351
352 return error;
353 }
354
355 void OptionParsingStarting(ExecutionContext *execution_context) override {
356 m_cascade = true;
357 m_class_name = "";
358 m_skip_pointers = false;
359 m_skip_references = false;
360 m_category = "default";
361 is_class_based = false;
362 handwrite_python = false;
364 }
365
366 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
367 return llvm::ArrayRef(g_type_synth_add_options);
368 }
369
370 // Instance variables to hold the values for command options.
371
375 std::string m_class_name;
377 std::string m_category;
381 };
382
384
385 Options *GetOptions() override { return &m_options; }
386
387 bool Execute_HandwritePython(Args &command, CommandReturnObject &result);
388
389 bool Execute_PythonClass(Args &command, CommandReturnObject &result);
390
391protected:
392 void DoExecute(Args &command, CommandReturnObject &result) override {
394
396 Execute_HandwritePython(command, result);
397 else if (m_options.is_class_based)
398 Execute_PythonClass(command, result);
399 else {
400 result.AppendError("must either provide a children list, a Python class "
401 "name, or use -P and type a Python class "
402 "line-by-line");
403 }
404 }
405
406 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
407 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
408 if (output_sp && interactive) {
409 output_sp->PutCString(g_synth_addreader_instructions);
410 output_sp->Flush();
411 }
412 }
413
415 std::string &data) override {
416 StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
417
418#if LLDB_ENABLE_PYTHON
420 if (interpreter) {
421 StringList lines;
422 lines.SplitIntoLines(data);
423 if (lines.GetSize() > 0) {
424 SynthAddOptions *options_ptr =
425 ((SynthAddOptions *)io_handler.GetUserData());
426 if (options_ptr) {
428 options_ptr); // this will ensure that we get rid of the pointer
429 // when going out of scope
430
432 if (interpreter) {
433 std::string class_name_str;
434 if (interpreter->GenerateTypeSynthClass(lines, class_name_str)) {
435 if (class_name_str.empty()) {
436 error_sp->Printf(
437 "error: unable to obtain a proper name for the class.\n");
438 error_sp->Flush();
439 } else {
440 // everything should be fine now, let's add the synth provider
441 // class
442
443 SyntheticChildrenSP synth_provider;
444 synth_provider = std::make_shared<ScriptedSyntheticChildren>(
446 .SetCascades(options->m_cascade)
447 .SetSkipPointers(options->m_skip_pointers)
448 .SetSkipReferences(options->m_skip_references),
449 class_name_str.c_str());
450
453 ConstString(options->m_category.c_str()), category);
454
456
457 for (const std::string &type_name : options->m_target_types) {
458 if (!type_name.empty()) {
459 if (AddSynth(ConstString(type_name), synth_provider,
460 options->m_match_type, options->m_category,
461 &error)) {
462 error_sp->Printf("error: %s\n", error.AsCString());
463 error_sp->Flush();
464 break;
465 }
466 } else {
467 error_sp->Printf("error: invalid type name.\n");
468 error_sp->Flush();
469 break;
470 }
471 }
472 }
473 } else {
474 error_sp->Printf("error: unable to generate a class.\n");
475 error_sp->Flush();
476 }
477 } else {
478 error_sp->Printf("error: no script interpreter.\n");
479 error_sp->Flush();
480 }
481 } else {
482 error_sp->Printf("error: internal synchronization data missing.\n");
483 error_sp->Flush();
484 }
485 } else {
486 error_sp->Printf("error: empty function, didn't add python command.\n");
487 error_sp->Flush();
488 }
489 } else {
490 error_sp->Printf(
491 "error: script interpreter missing, didn't add python command.\n");
492 error_sp->Flush();
493 }
494
495#endif
496 io_handler.SetIsDone(true);
497 }
498
499public:
501
502 ~CommandObjectTypeSynthAdd() override = default;
503
504 bool AddSynth(ConstString type_name, lldb::SyntheticChildrenSP entry,
505 FormatterMatchType match_type, std::string category_name,
506 Status *error);
507};
508
509// CommandObjectTypeFormatAdd
510
511#define LLDB_OPTIONS_type_format_add
512#include "CommandOptions.inc"
513
515private:
517 public:
518 CommandOptions() = default;
519
520 ~CommandOptions() override = default;
521
522 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
523 return llvm::ArrayRef(g_type_format_add_options);
524 }
525
526 void OptionParsingStarting(ExecutionContext *execution_context) override {
527 m_cascade = true;
528 m_skip_pointers = false;
529 m_skip_references = false;
530 m_regex = false;
531 m_category.assign("default");
532 m_custom_type_name.clear();
533 }
534
535 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
536 ExecutionContext *execution_context) override {
538 const int short_option =
539 g_type_format_add_options[option_idx].short_option;
540 bool success;
541
542 switch (short_option) {
543 case 'C':
544 m_cascade = OptionArgParser::ToBoolean(option_value, true, &success);
545 if (!success)
547 "invalid value for cascade: %s", option_value.str().c_str());
548 break;
549 case 'p':
550 m_skip_pointers = true;
551 break;
552 case 'w':
553 m_category.assign(std::string(option_value));
554 break;
555 case 'r':
556 m_skip_references = true;
557 break;
558 case 'x':
559 m_regex = true;
560 break;
561 case 't':
562 m_custom_type_name.assign(std::string(option_value));
563 break;
564 default:
565 llvm_unreachable("Unimplemented option");
566 }
567
568 return error;
569 }
570
571 // Instance variables to hold the values for command options.
572
577 std::string m_category;
579 };
580
584
585 Options *GetOptions() override { return &m_option_group; }
586
587public:
589 : CommandObjectParsed(interpreter, "type format add",
590 "Add a new formatting style for a type.", nullptr),
593
595 R"(
596The following examples of 'type format add' refer to this code snippet for context:
597
598 typedef int Aint;
599 typedef float Afloat;
600 typedef Aint Bint;
601 typedef Afloat Bfloat;
602
603 Aint ix = 5;
604 Bint iy = 5;
605
606 Afloat fx = 3.14;
607 BFloat fy = 3.14;
608
609Adding default formatting:
611(lldb) type format add -f hex AInt
612(lldb) frame variable iy
614)"
615 " Produces hexadecimal display of iy, because no formatter is available for Bint and \
616the one for Aint is used instead."
617 R"(
618
619To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains:
620
621
622(lldb) type format add -f hex -C no AInt
623
624Similar reasoning applies to this:
625
626(lldb) type format add -f hex -C no float -p
627
628)"
629 " All float values and float references are now formatted as hexadecimal, but not \
630pointers to floats. Nor will it change the default display for Afloat and Bfloat objects.");
631
632 // Add the "--format" to all options groups
638 }
639
640 ~CommandObjectTypeFormatAdd() override = default;
641
642protected:
643 void DoExecute(Args &command, CommandReturnObject &result) override {
644 const size_t argc = command.GetArgumentCount();
645
646 if (argc < 1) {
647 result.AppendErrorWithFormat("%s takes one or more args.\n",
648 m_cmd_name.c_str());
649 return;
650 }
651
652 const Format format = m_format_options.GetFormat();
653 if (format == eFormatInvalid &&
655 result.AppendErrorWithFormat("%s needs a valid format.\n",
656 m_cmd_name.c_str());
657 return;
658 }
659
660 TypeFormatImplSP entry;
661
663 entry = std::make_shared<TypeFormatImpl_Format>(
664 format, TypeFormatImpl::Flags()
665 .SetCascades(m_command_options.m_cascade)
668 else
669 entry = std::make_shared<TypeFormatImpl_EnumType>(
675
676 // now I have a valid format, let's add it to every type
677
678 TypeCategoryImplSP category_sp;
681 if (!category_sp)
682 return;
683
685
686 for (auto &arg_entry : command.entries()) {
687 if (arg_entry.ref().empty()) {
688 result.AppendError("empty typenames not allowed");
689 return;
690 }
691
694 match_type = eFormatterMatchRegex;
695 RegularExpression typeRX(arg_entry.ref());
696 if (!typeRX.IsValid()) {
697 result.AppendError(
698 "regex format error (maybe this is not really a regex?)");
699 return;
700 }
701 }
702 category_sp->AddTypeFormat(arg_entry.ref(), match_type, entry);
703 }
704
706 }
707};
708
709#define LLDB_OPTIONS_type_formatter_delete
710#include "CommandOptions.inc"
711
713protected:
714 class CommandOptions : public Options {
715 public:
716 CommandOptions() = default;
717
718 ~CommandOptions() override = default;
719
720 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
721 ExecutionContext *execution_context) override {
723 const int short_option = m_getopt_table[option_idx].val;
724
725 switch (short_option) {
726 case 'a':
727 m_delete_all = true;
728 break;
729 case 'w':
730 m_category = std::string(option_arg);
731 break;
732 case 'l':
734 break;
735 default:
736 llvm_unreachable("Unimplemented option");
737 }
738
739 return error;
740 }
741
742 void OptionParsingStarting(ExecutionContext *execution_context) override {
743 m_delete_all = false;
744 m_category = "default";
746 }
747
748 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
749 return llvm::ArrayRef(g_type_formatter_delete_options);
750 }
751
752 // Instance variables to hold the values for command options.
753
755 std::string m_category;
757 };
758
761
762 Options *GetOptions() override { return &m_options; }
763
764 static constexpr const char *g_short_help_template =
765 "Delete an existing %s for a type.";
766
767 static constexpr const char *g_long_help_template =
768 "Delete an existing %s for a type. Unless you specify a "
769 "specific category or all categories, only the "
770 "'default' category is searched. The names must be exactly as "
771 "shown in the 'type %s list' output";
772
773public:
775 FormatCategoryItem formatter_kind)
776 : CommandObjectParsed(interpreter,
777 FormatCategoryToString(formatter_kind, false)),
778 m_formatter_kind(formatter_kind) {
780
781 const char *kind = FormatCategoryToString(formatter_kind, true);
782 const char *short_kind = FormatCategoryToString(formatter_kind, false);
783
784 StreamString s;
786 SetHelp(s.GetData());
787 s.Clear();
788 s.Printf(g_long_help_template, kind, short_kind);
789 SetHelpLong(s.GetData());
790 s.Clear();
791 s.Printf("type %s delete", short_kind);
793 }
794
796
797 void
799 OptionElementVector &opt_element_vector) override {
800 if (request.GetCursorIndex())
801 return;
802
804 [this, &request](const lldb::TypeCategoryImplSP &category_sp) {
805 category_sp->AutoComplete(request, m_formatter_kind);
806 return true;
807 });
808 }
809
810protected:
811 virtual bool FormatterSpecificDeletion(ConstString typeCS) { return false; }
812
813 void DoExecute(Args &command, CommandReturnObject &result) override {
814 const size_t argc = command.GetArgumentCount();
815
816 if (argc != 1) {
817 result.AppendErrorWithFormat("%s takes 1 arg.\n", m_cmd_name.c_str());
818 return;
819 }
820
821 const char *typeA = command.GetArgumentAtIndex(0);
822 ConstString typeCS(typeA);
823
824 if (!typeCS) {
825 result.AppendError("empty typenames not allowed");
826 return;
827 }
828
831 [this, typeCS](const lldb::TypeCategoryImplSP &category_sp) -> bool {
832 category_sp->Delete(typeCS, m_formatter_kind);
833 return true;
834 });
836 return;
837 }
838
839 bool delete_category = false;
840 bool extra_deletion = false;
841
845 category);
846 if (category)
847 delete_category = category->Delete(typeCS, m_formatter_kind);
848 extra_deletion = FormatterSpecificDeletion(typeCS);
849 } else {
852 ConstString(m_options.m_category.c_str()), category);
853 if (category)
854 delete_category = category->Delete(typeCS, m_formatter_kind);
855 extra_deletion = FormatterSpecificDeletion(typeCS);
856 }
857
858 if (delete_category || extra_deletion) {
860 } else {
861 result.AppendErrorWithFormat("no custom formatter for %s.\n", typeA);
862 }
863 }
864};
865
866#define LLDB_OPTIONS_type_formatter_clear
867#include "CommandOptions.inc"
868
870private:
871 class CommandOptions : public Options {
872 public:
873 CommandOptions() = default;
874
875 ~CommandOptions() override = default;
876
877 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
878 ExecutionContext *execution_context) override {
880 const int short_option = m_getopt_table[option_idx].val;
881
882 switch (short_option) {
883 case 'a':
884 m_delete_all = true;
885 break;
886 default:
887 llvm_unreachable("Unimplemented option");
888 }
889
890 return error;
891 }
892
893 void OptionParsingStarting(ExecutionContext *execution_context) override {
894 m_delete_all = false;
895 }
896
897 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
898 return llvm::ArrayRef(g_type_formatter_clear_options);
899 }
900
901 // Instance variables to hold the values for command options.
903 };
904
907
908 Options *GetOptions() override { return &m_options; }
909
910public:
912 FormatCategoryItem formatter_kind,
913 const char *name, const char *help)
914 : CommandObjectParsed(interpreter, name, help, nullptr),
915 m_formatter_kind(formatter_kind) {
917 }
918
920
921protected:
923
924 void DoExecute(Args &command, CommandReturnObject &result) override {
927 [this](const TypeCategoryImplSP &category_sp) -> bool {
928 category_sp->Clear(m_formatter_kind);
929 return true;
930 });
931 } else {
933 if (command.GetArgumentCount() > 0) {
934 const char *cat_name = command.GetArgumentAtIndex(0);
935 ConstString cat_nameCS(cat_name);
936 DataVisualization::Categories::GetCategory(cat_nameCS, category);
937 } else {
939 category);
940 }
941 category->Clear(m_formatter_kind);
942 }
943
945
947 }
948};
949
950// CommandObjectTypeFormatDelete
951
953public:
956 interpreter, eFormatCategoryItemFormat) {}
957
958 ~CommandObjectTypeFormatDelete() override = default;
959};
960
961// CommandObjectTypeFormatClear
962
964public:
967 "type format clear",
968 "Delete all existing format styles.") {}
969};
970
971#define LLDB_OPTIONS_type_formatter_list
972#include "CommandOptions.inc"
973
974template <typename FormatterType>
976 typedef typename FormatterType::SharedPointer FormatterSharedPointer;
977
978 class CommandOptions : public Options {
979 public:
981 : Options(), m_category_regex("", ""),
984
985 ~CommandOptions() override = default;
986
987 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
988 ExecutionContext *execution_context) override {
990 const int short_option = m_getopt_table[option_idx].val;
991 switch (short_option) {
992 case 'w':
995 break;
996 case 'l':
998 if (error.Success())
1000 break;
1001 default:
1002 llvm_unreachable("Unimplemented option");
1003 }
1004
1005 return error;
1006 }
1007
1008 void OptionParsingStarting(ExecutionContext *execution_context) override {
1011 }
1012
1013 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1014 return llvm::ArrayRef(g_type_formatter_list_options);
1015 }
1016
1017 // Instance variables to hold the values for command options.
1018
1021 };
1022
1024
1025 Options *GetOptions() override { return &m_options; }
1026
1027public:
1029 const char *name, const char *help)
1030 : CommandObjectParsed(interpreter, name, help, nullptr), m_options() {
1032 }
1033
1035
1036protected:
1038 return false;
1039 }
1040
1041 static bool ShouldListItem(llvm::StringRef s, RegularExpression *regex) {
1042 // If we have a regex, it can match two kinds of results:
1043 // - An item created with that same regex string (exact string match), so
1044 // the user can list it using the same string it used at creation time.
1045 // - Items that match the regex.
1046 // No regex means list everything.
1047 return regex == nullptr || s == regex->GetText() || regex->Execute(s);
1048 }
1049
1050 void DoExecute(Args &command, CommandReturnObject &result) override {
1051 const size_t argc = command.GetArgumentCount();
1052
1053 std::unique_ptr<RegularExpression> category_regex;
1054 std::unique_ptr<RegularExpression> formatter_regex;
1055
1057 category_regex = std::make_unique<RegularExpression>(
1059 if (!category_regex->IsValid()) {
1060 result.AppendErrorWithFormat(
1061 "syntax error in category regular expression '%s'",
1063 return;
1064 }
1065 }
1066
1067 if (argc == 1) {
1068 const char *arg = command.GetArgumentAtIndex(0);
1069 formatter_regex = std::make_unique<RegularExpression>(arg);
1070 if (!formatter_regex->IsValid()) {
1071 result.AppendErrorWithFormat("syntax error in regular expression '%s'",
1072 arg);
1073 return;
1074 }
1075 }
1076
1077 bool any_printed = false;
1078
1079 auto category_closure =
1080 [&result, &formatter_regex,
1081 &any_printed](const lldb::TypeCategoryImplSP &category) -> void {
1082 result.GetOutputStream().Printf(
1083 "-----------------------\nCategory: %s%s\n-----------------------\n",
1084 category->GetName(), category->IsEnabled() ? "" : " (disabled)");
1085
1087 [&result, &formatter_regex,
1088 &any_printed](const TypeMatcher &type_matcher,
1089 const FormatterSharedPointer &format_sp) -> bool {
1090 if (ShouldListItem(type_matcher.GetMatchString().GetStringRef(),
1091 formatter_regex.get())) {
1092 any_printed = true;
1093 result.GetOutputStream().Printf(
1094 "%s: %s\n", type_matcher.GetMatchString().GetCString(),
1095 format_sp->GetDescription().c_str());
1096 }
1097 return true;
1098 };
1099 category->ForEach(print_formatter);
1100 };
1101
1103 lldb::TypeCategoryImplSP category_sp;
1106 if (category_sp)
1107 category_closure(category_sp);
1108 } else {
1110 [&category_regex, &category_closure](
1111 const lldb::TypeCategoryImplSP &category) -> bool {
1112 if (ShouldListItem(category->GetName(), category_regex.get())) {
1113 category_closure(category);
1114 }
1115 return true;
1116 });
1117
1118 any_printed = FormatterSpecificList(result) | any_printed;
1119 }
1120
1121 if (any_printed)
1123 else {
1124 result.GetOutputStream().PutCString("no matching results found.\n");
1126 }
1127 }
1128};
1129
1130// CommandObjectTypeFormatList
1131
1133 : public CommandObjectTypeFormatterList<TypeFormatImpl> {
1134public:
1136 : CommandObjectTypeFormatterList(interpreter, "type format list",
1137 "Show a list of current formats.") {}
1138};
1139
1141 uint32_t option_idx, llvm::StringRef option_arg,
1142 ExecutionContext *execution_context) {
1143 Status error;
1144 const int short_option = m_getopt_table[option_idx].val;
1145 bool success;
1146
1147 switch (short_option) {
1148 case 'C':
1149 m_flags.SetCascades(OptionArgParser::ToBoolean(option_arg, true, &success));
1150 if (!success)
1151 error = Status::FromErrorStringWithFormat("invalid value for cascade: %s",
1152 option_arg.str().c_str());
1153 break;
1154 case 'e':
1156 break;
1157 case 'h':
1159 break;
1160 case 'v':
1162 break;
1163 case 'c':
1165 break;
1166 case 's':
1167 m_format_string = std::string(option_arg);
1168 break;
1169 case 'p':
1171 break;
1172 case 'r':
1174 break;
1175 case 'x':
1178 "can't use --regex and --recognizer-function at the same time");
1179 else
1181 break;
1182 case '\x01':
1185 "can't use --regex and --recognizer-function at the same time");
1186 else
1188 break;
1189 case 'n':
1190 m_name.SetString(option_arg);
1191 break;
1192 case 'o':
1193 m_python_script = std::string(option_arg);
1194 m_is_add_script = true;
1195 break;
1196 case 'F':
1197 m_python_function = std::string(option_arg);
1198 m_is_add_script = true;
1199 break;
1200 case 'P':
1201 m_is_add_script = true;
1202 break;
1203 case 'w':
1204 m_category = std::string(option_arg);
1205 break;
1206 case 'O':
1208 break;
1209 default:
1210 llvm_unreachable("Unimplemented option");
1211 }
1212
1213 return error;
1214}
1215
1217 ExecutionContext *execution_context) {
1218 m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false);
1219 m_flags.SetShowMembersOneLiner(false)
1220 .SetSkipPointers(false)
1221 .SetSkipReferences(false)
1222 .SetHideItemNames(false);
1223
1224 m_match_type = eFormatterMatchExact;
1225 m_name.Clear();
1226 m_python_script = "";
1227 m_python_function = "";
1228 m_format_string = "";
1229 m_is_add_script = false;
1230 m_category = "default";
1231}
1232
1233#if LLDB_ENABLE_PYTHON
1234
1236 Args &command, CommandReturnObject &result) {
1237 const size_t argc = command.GetArgumentCount();
1238
1239 if (argc < 1 && !m_options.m_name) {
1240 result.AppendErrorWithFormat("%s takes one or more args.\n",
1241 m_cmd_name.c_str());
1242 return false;
1243 }
1244
1245 TypeSummaryImplSP script_format;
1246
1248 .empty()) // we have a Python function ready to use
1249 {
1250 const char *funct_name = m_options.m_python_function.c_str();
1251 if (!funct_name || !funct_name[0]) {
1252 result.AppendError("function name empty.\n");
1253 return false;
1254 }
1255
1256 std::string code =
1257 (" " + m_options.m_python_function + "(valobj,internal_dict)");
1258
1259 script_format = std::make_shared<ScriptSummaryFormat>(
1260 m_options.m_flags, funct_name, code.c_str());
1261
1263
1264 if (interpreter && !interpreter->CheckObjectExists(funct_name))
1266 "The provided function \"%s\" does not exist - "
1267 "please define it before attempting to use this summary.\n",
1268 funct_name);
1269 } else if (!m_options.m_python_script
1270 .empty()) // we have a quick 1-line script, just use it
1271 {
1273 if (!interpreter) {
1274 result.AppendError("script interpreter missing - unable to generate "
1275 "function wrapper.\n");
1276 return false;
1277 }
1278 StringList funct_sl;
1279 funct_sl << m_options.m_python_script.c_str();
1280 std::string funct_name_str;
1281 if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) {
1282 result.AppendError("unable to generate function wrapper.\n");
1283 return false;
1284 }
1285 if (funct_name_str.empty()) {
1286 result.AppendError(
1287 "script interpreter failed to generate a valid function name.\n");
1288 return false;
1289 }
1290
1291 std::string code = " " + m_options.m_python_script;
1292
1293 script_format = std::make_shared<ScriptSummaryFormat>(
1294 m_options.m_flags, funct_name_str.c_str(), code.c_str());
1295 } else {
1296 // Use an IOHandler to grab Python code from the user
1297 auto options = std::make_unique<ScriptAddOptions>(
1300
1301 for (auto &entry : command.entries()) {
1302 if (entry.ref().empty()) {
1303 result.AppendError("empty typenames not allowed");
1304 return false;
1305 }
1306
1307 options->m_target_types << std::string(entry.ref());
1308 }
1309
1311 " ", // Prompt
1312 *this, // IOHandlerDelegate
1313 options.release()); // Baton for the "io_handler" that will be passed
1314 // back into our IOHandlerDelegate functions
1316
1317 return result.Succeeded();
1318 }
1319
1320 // if I am here, script_format must point to something good, so I can add
1321 // that as a script summary to all interested parties
1322
1323 Status error;
1324
1325 for (auto &entry : command.entries()) {
1326 AddSummary(ConstString(entry.ref()), script_format, m_options.m_match_type,
1328 if (error.Fail()) {
1329 result.AppendError(error.AsCString());
1330 return false;
1331 }
1332 }
1333
1334 if (m_options.m_name) {
1335 AddNamedSummary(m_options.m_name, script_format, &error);
1336 if (error.Fail()) {
1337 result.AppendError(error.AsCString());
1338 result.AppendError("added to types, but not given a name");
1339 return false;
1340 }
1341 }
1342
1343 return result.Succeeded();
1344}
1345
1346#endif
1347
1349 Args &command, CommandReturnObject &result) {
1350 const size_t argc = command.GetArgumentCount();
1351
1352 if (argc < 1 && !m_options.m_name) {
1353 result.AppendErrorWithFormat("%s takes one or more args.\n",
1354 m_cmd_name.c_str());
1355 return false;
1356 }
1357
1359 m_options.m_format_string.empty()) {
1360 result.AppendError("empty summary strings not allowed");
1361 return false;
1362 }
1363
1364 const char *format_cstr = (m_options.m_flags.GetShowMembersOneLiner()
1365 ? ""
1366 : m_options.m_format_string.c_str());
1367
1368 // ${var%S} is an endless recursion, prevent it
1369 if (strcmp(format_cstr, "${var%S}") == 0) {
1370 result.AppendError("recursive summary not allowed");
1371 return false;
1372 }
1373
1374 std::unique_ptr<StringSummaryFormat> string_format(
1375 new StringSummaryFormat(m_options.m_flags, format_cstr));
1376 if (!string_format) {
1377 result.AppendError("summary creation failed");
1378 return false;
1379 }
1380 if (string_format->m_error.Fail()) {
1381 result.AppendErrorWithFormat("syntax error: %s",
1382 string_format->m_error.AsCString("<unknown>"));
1383 return false;
1384 }
1385 lldb::TypeSummaryImplSP entry(string_format.release());
1386
1387 // now I have a valid format, let's add it to every type
1388 Status error;
1389 for (auto &arg_entry : command.entries()) {
1390 if (arg_entry.ref().empty()) {
1391 result.AppendError("empty typenames not allowed");
1392 return false;
1393 }
1394 ConstString typeCS(arg_entry.ref());
1395
1397 &error);
1398
1399 if (error.Fail()) {
1400 result.AppendError(error.AsCString());
1401 return false;
1402 }
1403 }
1404
1405 if (m_options.m_name) {
1407 if (error.Fail()) {
1408 result.AppendError(error.AsCString());
1409 result.AppendError("added to types, but not given a name");
1410 return false;
1411 }
1412 }
1413
1415 return result.Succeeded();
1416}
1417
1419 CommandInterpreter &interpreter)
1420 : CommandObjectParsed(interpreter, "type summary add",
1421 "Add a new summary style for a type.", nullptr),
1422 IOHandlerDelegateMultiline("DONE"), m_options(interpreter) {
1424
1426 R"(
1427The following examples of 'type summary add' refer to this code snippet for context:
1428
1429 struct JustADemo
1430 {
1431 int* ptr;
1432 float value;
1433 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
1434 };
1435 JustADemo demo_instance(42, 3.14);
1436
1437 typedef JustADemo NewDemo;
1438 NewDemo new_demo_instance(42, 3.14);
1439
1440(lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo
1441
1442 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"
1443
1444(lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo
1445
1446 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"
1447
1448)"
1449 "Alternatively, you could define formatting for all pointers to integers and \
1450rely on that when formatting JustADemo to obtain the same result:"
1451 R"(
1452
1453(lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
1454(lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo
1456)"
1457 "Type summaries are automatically applied to derived typedefs, so the examples \
1458above apply to both JustADemo and NewDemo. The cascade option can be used to \
1459suppress this behavior:"
1460 R"(
1461
1462(lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no
1463
1464 The summary will now be used for values of JustADemo but not NewDemo.
1465
1466)"
1467 "By default summaries are shown for pointers and references to values of the \
1468specified type. To suppress formatting for pointers use the -p option, or apply \
1469the corresponding -r option to suppress formatting for references:"
1470 R"(
1472(lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo
1473
1474)"
1475 "One-line summaries including all fields in a type can be inferred without supplying an \
1476explicit summary string by passing the -c option:"
1477 R"(
1478
1479(lldb) type summary add -c JustADemo
1480(lldb) frame variable demo_instance
1481(ptr=<address>, value=3.14)
1482
1483)"
1484 "Type summaries normally suppress the nested display of individual fields. To \
1485supply a summary to supplement the default structure add the -e option:"
1486 R"(
1488(lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo
1489
1490)"
1491 "Now when displaying JustADemo values the int* is displayed, followed by the \
1492standard LLDB sequence of children, one per line:"
1493 R"(
1494
1495*ptr = 42 {
1496 ptr = <address>
1497 value = 3.14
1498}
1499
1500)"
1501 "You can also add summaries written in Python. These scripts use lldb public API to \
1502gather information from your variables and produce a meaningful summary. To start a \
1503multi-line script use the -P option. The function declaration will be displayed along with \
1504a comment describing the two arguments. End your script with the word 'DONE' on a line by \
1505itself:"
1506 R"(
1507
1508(lldb) type summary add JustADemo -P
1509def function (valobj,internal_dict): """valobj: an SBValue which you want to provide a summary for
1510internal_dict: an LLDB support object not to be used"""
1511 value = valobj.GetChildMemberWithName('value');
1512 return 'My value is ' + value.GetValue();
1513 DONE
1514
1515Alternatively, the -o option can be used when providing a simple one-line Python script:
1516
1517(lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")");
1518}
1519
1521 CommandReturnObject &result) {
1522 WarnOnPotentialUnquotedUnsignedType(command, result);
1523
1525#if LLDB_ENABLE_PYTHON
1526 Execute_ScriptSummary(command, result);
1527#else
1528 result.AppendError("python is disabled");
1529#endif
1530 return;
1531 }
1532
1533 Execute_StringSummary(command, result);
1534}
1535
1536static bool FixArrayTypeNameWithRegex(ConstString &type_name) {
1537 llvm::StringRef type_name_ref(type_name.GetStringRef());
1538
1539 if (type_name_ref.ends_with("[]")) {
1540 std::string type_name_str(type_name.GetCString());
1541 type_name_str.resize(type_name_str.length() - 2);
1542 if (type_name_str.back() != ' ')
1543 type_name_str.append(" ?\\[[0-9]+\\]");
1544 else
1545 type_name_str.append("\\[[0-9]+\\]");
1546 type_name.SetCString(type_name_str.c_str());
1547 return true;
1548 }
1549 return false;
1550}
1551
1554 Status *error) {
1555 // system named summaries do not exist (yet?)
1557 return true;
1558}
1559
1562 FormatterMatchType match_type,
1563 std::string category_name,
1564 Status *error) {
1565 lldb::TypeCategoryImplSP category;
1567 category);
1569 if (match_type == eFormatterMatchExact) {
1570 if (FixArrayTypeNameWithRegex(type_name))
1572 }
1573
1574 if (match_type == eFormatterMatchRegex) {
1575 match_type = eFormatterMatchRegex;
1576 RegularExpression typeRX(type_name.GetStringRef());
1577 if (!typeRX.IsValid()) {
1578 if (error)
1580 "regex format error (maybe this is not really a regex?)");
1581 return false;
1582 }
1583 }
1584
1585 if (match_type == eFormatterMatchCallback) {
1586 const char *function_name = type_name.AsCString();
1588 if (interpreter && !interpreter->CheckObjectExists(function_name)) {
1590 "The provided recognizer function \"%s\" does not exist - "
1591 "please define it before attempting to use this summary.\n",
1592 function_name);
1593 return false;
1595 }
1596 category->AddTypeSummary(type_name.GetStringRef(), match_type, entry);
1597 return true;
1599
1600// CommandObjectTypeSummaryDelete
1601
1603public:
1607
1608 ~CommandObjectTypeSummaryDelete() override = default;
1609
1610protected:
1611 bool FormatterSpecificDeletion(ConstString typeCS) override {
1613 return false;
1615 }
1616};
1617
1619public:
1622 "type summary clear",
1623 "Delete all existing summaries.") {}
1624
1625protected:
1626 void FormatterSpecificDeletion() override {
1628 }
1629};
1631// CommandObjectTypeSummaryList
1632
1634 : public CommandObjectTypeFormatterList<TypeSummaryImpl> {
1635public:
1637 : CommandObjectTypeFormatterList(interpreter, "type summary list",
1638 "Show a list of current summaries.") {}
1639
1640protected:
1641 bool FormatterSpecificList(CommandReturnObject &result) override {
1643 result.GetOutputStream().Printf("Named summaries:\n");
1645 [&result](const TypeMatcher &type_matcher,
1646 const TypeSummaryImplSP &summary_sp) -> bool {
1647 result.GetOutputStream().Printf(
1648 "%s: %s\n", type_matcher.GetMatchString().GetCString(),
1649 summary_sp->GetDescription().c_str());
1650 return true;
1651 });
1652 return true;
1653 }
1654 return false;
1656};
1657
1658// CommandObjectTypeCategoryDefine
1659#define LLDB_OPTIONS_type_category_define
1660#include "CommandOptions.inc"
1661
1663 class CommandOptions : public Options {
1664 public:
1666 : m_define_enabled(false, false),
1668
1669 ~CommandOptions() override = default;
1670
1671 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1672 ExecutionContext *execution_context) override {
1673 Status error;
1674 const int short_option = m_getopt_table[option_idx].val;
1675
1676 switch (short_option) {
1677 case 'e':
1678 m_define_enabled.SetValueFromString(llvm::StringRef("true"));
1679 break;
1680 case 'l':
1682 break;
1683 default:
1684 llvm_unreachable("Unimplemented option");
1686
1687 return error;
1688 }
1690 void OptionParsingStarting(ExecutionContext *execution_context) override {
1693 }
1694
1695 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1696 return llvm::ArrayRef(g_type_category_define_options);
1697 }
1698
1699 // Instance variables to hold the values for command options.
1700
1703 };
1704
1705 CommandOptions m_options;
1706
1707 Options *GetOptions() override { return &m_options; }
1708
1709public:
1711 : CommandObjectParsed(interpreter, "type category define",
1712 "Define a new category as a source of formatters.",
1713 nullptr) {
1715 }
1717 ~CommandObjectTypeCategoryDefine() override = default;
1718
1719protected:
1720 void DoExecute(Args &command, CommandReturnObject &result) override {
1721 const size_t argc = command.GetArgumentCount();
1723 if (argc < 1) {
1724 result.AppendErrorWithFormat("%s takes 1 or more args.\n",
1725 m_cmd_name.c_str());
1726 return;
1728
1729 for (auto &entry : command.entries()) {
1732 category_sp) &&
1733 category_sp) {
1734 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue());
1738 }
1739 }
1742 }
1743};
1744
1745// CommandObjectTypeCategoryEnable
1746#define LLDB_OPTIONS_type_category_enable
1747#include "CommandOptions.inc"
1748
1750 class CommandOptions : public Options {
1751 public:
1752 CommandOptions() = default;
1753
1754 ~CommandOptions() override = default;
1755
1756 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1757 ExecutionContext *execution_context) override {
1758 Status error;
1759 const int short_option = m_getopt_table[option_idx].val;
1760
1761 switch (short_option) {
1762 case 'l':
1763 if (!option_arg.empty()) {
1767 "unrecognized language '%s'", option_arg.str().c_str());
1768 }
1769 break;
1770 default:
1771 llvm_unreachable("Unimplemented option");
1772 }
1773
1774 return error;
1775 }
1776
1777 void OptionParsingStarting(ExecutionContext *execution_context) override {
1780
1781 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1782 return llvm::ArrayRef(g_type_category_enable_options);
1783 }
1784
1785 // Instance variables to hold the values for command options.
1786
1789
1790 CommandOptions m_options;
1792 Options *GetOptions() override { return &m_options; }
1793
1794public:
1796 : CommandObjectParsed(interpreter, "type category enable",
1797 "Enable a category as a source of formatters.",
1798 nullptr) {
1800 }
1801
1802 ~CommandObjectTypeCategoryEnable() override = default;
1803
1804protected:
1805 void DoExecute(Args &command, CommandReturnObject &result) override {
1806 const size_t argc = command.GetArgumentCount();
1807
1808 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
1809 result.AppendErrorWithFormat("%s takes arguments and/or a language",
1810 m_cmd_name.c_str());
1811 return;
1812 }
1813
1814 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
1816 } else if (argc > 0) {
1817 for (int i = argc - 1; i >= 0; i--) {
1818 const char *typeA = command.GetArgumentAtIndex(i);
1819 ConstString typeCS(typeA);
1820
1821 if (!typeCS) {
1822 result.AppendError("empty category name not allowed");
1823 return;
1824 }
1828 if (cate->GetCount() == 0) {
1829 result.AppendWarning("empty category enabled (typo?)");
1830 }
1832 }
1834
1837
1839 }
1840};
1841
1842// CommandObjectTypeCategoryDelete
1843
1845public:
1847 : CommandObjectParsed(interpreter, "type category delete",
1848 "Delete a category and all associated formatters.",
1849 nullptr) {
1851 }
1852
1853 ~CommandObjectTypeCategoryDelete() override = default;
1855protected:
1856 void DoExecute(Args &command, CommandReturnObject &result) override {
1857 const size_t argc = command.GetArgumentCount();
1859 if (argc < 1) {
1860 result.AppendErrorWithFormat("%s takes 1 or more arg.\n",
1861 m_cmd_name.c_str());
1862 return;
1863 }
1865 bool success = true;
1866
1867 // the order is not relevant here
1868 for (int i = argc - 1; i >= 0; i--) {
1869 const char *typeA = command.GetArgumentAtIndex(i);
1870 ConstString typeCS(typeA);
1871
1872 if (!typeCS) {
1873 result.AppendError("empty category name not allowed");
1874 return;
1875 }
1877 success = false; // keep deleting even if we hit an error
1878 }
1879 if (success) {
1881 } else {
1882 result.AppendError("cannot delete one or more categories\n");
1883 }
1884 }
1885};
1886
1887// CommandObjectTypeCategoryDisable
1888#define LLDB_OPTIONS_type_category_disable
1889#include "CommandOptions.inc"
1890
1892 class CommandOptions : public Options {
1893 public:
1894 CommandOptions() = default;
1895
1896 ~CommandOptions() override = default;
1897
1898 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1899 ExecutionContext *execution_context) override {
1900 Status error;
1901 const int short_option = m_getopt_table[option_idx].val;
1902
1903 switch (short_option) {
1904 case 'l':
1905 if (!option_arg.empty()) {
1909 "unrecognized language '%s'", option_arg.str().c_str());
1910 }
1911 break;
1912 default:
1913 llvm_unreachable("Unimplemented option");
1914 }
1915
1916 return error;
1917 }
1919 void OptionParsingStarting(ExecutionContext *execution_context) override {
1921 }
1922
1923 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1924 return llvm::ArrayRef(g_type_category_disable_options);
1926
1927 // Instance variables to hold the values for command options.
1930 };
1931
1932 CommandOptions m_options;
1933
1934 Options *GetOptions() override { return &m_options; }
1935
1936public:
1938 : CommandObjectParsed(interpreter, "type category disable",
1939 "Disable a category as a source of formatters.",
1940 nullptr) {
1942 }
1943
1944 ~CommandObjectTypeCategoryDisable() override = default;
1945
1946protected:
1947 void DoExecute(Args &command, CommandReturnObject &result) override {
1948 const size_t argc = command.GetArgumentCount();
1949
1950 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) {
1951 result.AppendErrorWithFormat("%s takes arguments and/or a language",
1952 m_cmd_name.c_str());
1953 return;
1954 }
1955
1956 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) {
1958 } else if (argc > 0) {
1959 // the order is not relevant here
1960 for (int i = argc - 1; i >= 0; i--) {
1961 const char *typeA = command.GetArgumentAtIndex(i);
1962 ConstString typeCS(typeA);
1963
1964 if (!typeCS) {
1965 result.AppendError("empty category name not allowed");
1966 return;
1967 }
1969 }
1970 }
1971
1974
1976 }
1977};
1978
1979// CommandObjectTypeCategoryList
1980
1982public:
1984 : CommandObjectParsed(interpreter, "type category list",
1985 "Provide a list of all existing categories.",
1986 nullptr) {
1988 }
1989
1990 ~CommandObjectTypeCategoryList() override = default;
1991
1992 void
1994 OptionElementVector &opt_element_vector) override {
1995 if (request.GetCursorIndex())
1996 return;
1999 nullptr);
2000 }
2001
2002protected:
2003 void DoExecute(Args &command, CommandReturnObject &result) override {
2004 const size_t argc = command.GetArgumentCount();
2005
2006 std::unique_ptr<RegularExpression> regex;
2007
2008 if (argc == 1) {
2009 const char *arg = command.GetArgumentAtIndex(0);
2010 regex = std::make_unique<RegularExpression>(arg);
2011 if (!regex->IsValid()) {
2012 result.AppendErrorWithFormat(
2013 "syntax error in category regular expression '%s'", arg);
2014 return;
2016 } else if (argc != 0) {
2017 result.AppendErrorWithFormat("%s takes 0 or one arg.\n",
2018 m_cmd_name.c_str());
2019 return;
2020 }
2023 [&regex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool {
2024 if (regex) {
2025 bool escape = true;
2026 if (regex->GetText() == category_sp->GetName()) {
2027 escape = false;
2028 } else if (regex->Execute(category_sp->GetName())) {
2029 escape = false;
2030 }
2031
2032 if (escape)
2033 return true;
2034 }
2035
2036 result.GetOutputStream().Printf(
2037 "Category: %s\n", category_sp->GetDescription().c_str());
2038
2039 return true;
2040 });
2041
2043 }
2044};
2046// CommandObjectTypeFilterList
2047
2049 : public CommandObjectTypeFormatterList<TypeFilterImpl> {
2050public:
2052 : CommandObjectTypeFormatterList(interpreter, "type filter list",
2053 "Show a list of current filters.") {}
2054};
2055
2056// CommandObjectTypeSynthList
2057
2059 : public CommandObjectTypeFormatterList<SyntheticChildren> {
2060public:
2063 interpreter, "type synthetic list",
2064 "Show a list of current synthetic providers.") {}
2065};
2066
2067// CommandObjectTypeFilterDelete
2068
2070public:
2073 interpreter, eFormatCategoryItemFilter) {}
2074
2075 ~CommandObjectTypeFilterDelete() override = default;
2076};
2077
2078// CommandObjectTypeSynthDelete
2079
2081public:
2084 interpreter, eFormatCategoryItemSynth) {}
2085
2086 ~CommandObjectTypeSynthDelete() override = default;
2087};
2088
2089
2090// CommandObjectTypeFilterClear
2091
2093public:
2096 "type filter clear",
2097 "Delete all existing filter.") {}
2098};
2099
2100// CommandObjectTypeSynthClear
2101
2103public:
2106 interpreter, eFormatCategoryItemSynth, "type synthetic clear",
2107 "Delete all existing synthetic providers.") {}
2108};
2109
2111 Args &command, CommandReturnObject &result) {
2112 auto options = std::make_unique<SynthAddOptions>(
2115
2116 for (auto &entry : command.entries()) {
2117 if (entry.ref().empty()) {
2118 result.AppendError("empty typenames not allowed");
2119 return false;
2120 }
2121
2122 options->m_target_types << std::string(entry.ref());
2123 }
2124
2126 " ", // Prompt
2127 *this, // IOHandlerDelegate
2128 options.release()); // Baton for the "io_handler" that will be passed back
2129 // into our IOHandlerDelegate functions
2131 return result.Succeeded();
2132}
2133
2135 Args &command, CommandReturnObject &result) {
2136 const size_t argc = command.GetArgumentCount();
2137
2138 if (argc < 1) {
2139 result.AppendErrorWithFormat("%s takes one or more args.\n",
2140 m_cmd_name.c_str());
2141 return false;
2142 }
2143
2145 result.AppendErrorWithFormat("%s needs either a Python class name or -P to "
2146 "directly input Python code.\n",
2147 m_cmd_name.c_str());
2148 return false;
2149 }
2150
2151 SyntheticChildrenSP entry;
2152
2155 .SetCascades(m_options.m_cascade)
2158 m_options.m_class_name.c_str());
2159
2160 entry.reset(impl);
2161
2163
2164 if (interpreter &&
2165 !interpreter->CheckObjectExists(impl->GetPythonClassName()))
2166 result.AppendWarning("The provided class does not exist - please define it "
2167 "before attempting to use this synthetic provider");
2168
2169 // now I have a valid provider, let's add it to every type
2170
2171 lldb::TypeCategoryImplSP category;
2173 ConstString(m_options.m_category.c_str()), category);
2174
2175 Status error;
2176
2177 for (auto &arg_entry : command.entries()) {
2178 if (arg_entry.ref().empty()) {
2179 result.AppendError("empty typenames not allowed");
2180 return false;
2181 }
2182
2183 ConstString typeCS(arg_entry.ref());
2184 if (!AddSynth(typeCS, entry, m_options.m_match_type, m_options.m_category,
2185 &error)) {
2186 result.AppendError(error.AsCString());
2187 return false;
2188 }
2189 }
2190
2192 return result.Succeeded();
2193}
2194
2196 CommandInterpreter &interpreter)
2197 : CommandObjectParsed(interpreter, "type synthetic add",
2198 "Add a new synthetic provider for a type.", nullptr),
2199 IOHandlerDelegateMultiline("DONE"), m_options() {
2200 AddSimpleArgumentList(eArgTypeName, eArgRepeatPlus);
2202
2205 FormatterMatchType match_type,
2206 std::string category_name,
2208 lldb::TypeCategoryImplSP category;
2210 category);
2212 if (match_type == eFormatterMatchExact) {
2213 if (FixArrayTypeNameWithRegex(type_name))
2214 match_type = eFormatterMatchRegex;
2215 }
2216
2217 // Only check for conflicting filters in the same category if `type_name` is
2218 // an actual type name. Matching a regex string against registered regexes
2219 // doesn't work.
2220 if (match_type == eFormatterMatchExact) {
2221 // It's not generally possible to get a type object here. For example, this
2222 // command can be run before loading any binaries. Do just a best-effort
2223 // name-based lookup here to try to prevent conflicts.
2224 FormattersMatchCandidate candidate_type(type_name, nullptr, TypeImpl(),
2226 if (category->AnyMatches(candidate_type, eFormatCategoryItemFilter,
2227 false)) {
2228 if (error)
2230 "cannot add synthetic for type %s when "
2231 "filter is defined in same category!",
2232 type_name.AsCString());
2233 return false;
2234 }
2235 }
2236
2237 if (match_type == eFormatterMatchRegex) {
2238 RegularExpression typeRX(type_name.GetStringRef());
2239 if (!typeRX.IsValid()) {
2240 if (error)
2242 "regex format error (maybe this is not really a regex?)");
2243 return false;
2244 }
2245 }
2246
2247 if (match_type == eFormatterMatchCallback) {
2248 const char *function_name = type_name.AsCString();
2250 if (interpreter && !interpreter->CheckObjectExists(function_name)) {
2252 "The provided recognizer function \"%s\" does not exist - "
2253 "please define it before attempting to use this summary.\n",
2254 function_name);
2255 return false;
2256 }
2258
2259 category->AddTypeSynthetic(type_name.GetStringRef(), match_type, entry);
2260 return true;
2261}
2262
2263#define LLDB_OPTIONS_type_filter_add
2264#include "CommandOptions.inc"
2267private:
2268 class CommandOptions : public Options {
2269 typedef std::vector<std::string> option_vector;
2271 public:
2272 CommandOptions() = default;
2273
2274 ~CommandOptions() override = default;
2276 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2277 ExecutionContext *execution_context) override {
2278 Status error;
2279 const int short_option = m_getopt_table[option_idx].val;
2280 bool success;
2282 switch (short_option) {
2283 case 'C':
2284 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success);
2285 if (!success)
2287 "invalid value for cascade: %s", option_arg.str().c_str());
2288 break;
2289 case 'c':
2290 m_expr_paths.push_back(std::string(option_arg));
2291 has_child_list = true;
2292 break;
2293 case 'p':
2294 m_skip_pointers = true;
2295 break;
2296 case 'r':
2297 m_skip_references = true;
2298 break;
2299 case 'w':
2300 m_category = std::string(option_arg);
2301 break;
2302 case 'x':
2303 m_regex = true;
2304 break;
2305 default:
2306 llvm_unreachable("Unimplemented option");
2307 }
2308
2309 return error;
2310 }
2311
2312 void OptionParsingStarting(ExecutionContext *execution_context) override {
2313 m_cascade = true;
2314 m_skip_pointers = false;
2315 m_skip_references = false;
2316 m_category = "default";
2317 m_expr_paths.clear();
2318 has_child_list = false;
2319 m_regex = false;
2320 }
2321
2322 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2323 return llvm::ArrayRef(g_type_filter_add_options);
2324 }
2325
2326 // Instance variables to hold the values for command options.
2327
2328 bool m_cascade;
2329 bool m_skip_references;
2330 bool m_skip_pointers;
2333 std::string m_category;
2334 bool has_child_list;
2335 bool m_regex;
2336
2337 typedef option_vector::iterator ExpressionPathsIterator;
2338 };
2339
2340 CommandOptions m_options;
2341
2342 Options *GetOptions() override { return &m_options; }
2343
2345
2347 FilterFormatType type, std::string category_name,
2348 Status *error) {
2351 ConstString(category_name.c_str()), category);
2352
2353 if (type == eRegularFilter) {
2354 if (FixArrayTypeNameWithRegex(type_name))
2355 type = eRegexFilter;
2356 }
2357
2358 // Only check for conflicting synthetic child providers in the same category
2359 // if `type_name` is an actual type name. Matching a regex string against
2360 // registered regexes doesn't work.
2361 if (type == eRegularFilter) {
2362 // It's not generally possible to get a type object here. For example,
2363 // this command can be run before loading any binaries. Do just a
2364 // best-effort name-based lookup here to try to prevent conflicts.
2365 FormattersMatchCandidate candidate_type(
2366 type_name, nullptr, TypeImpl(), FormattersMatchCandidate::Flags());
2368 if (category->AnyMatches(candidate_type, eFormatCategoryItemSynth,
2369 false)) {
2370 if (error)
2372 "cannot add filter for type %s when "
2373 "synthetic is defined in same "
2374 "category!",
2375 type_name.AsCString());
2376 return false;
2377 }
2378 }
2379
2381 if (type == eRegexFilter) {
2382 match_type = eFormatterMatchRegex;
2383 RegularExpression typeRX(type_name.GetStringRef());
2384 if (!typeRX.IsValid()) {
2385 if (error)
2387 "regex format error (maybe this is not really a regex?)");
2388 return false;
2389 }
2390 }
2391 category->AddTypeFilter(type_name.GetStringRef(), match_type, entry);
2392 return true;
2393 }
2394
2395public:
2397 : CommandObjectParsed(interpreter, "type filter add",
2398 "Add a new filter for a type.", nullptr) {
2400
2402 R"(
2403The following examples of 'type filter add' refer to this code snippet for context:
2404
2405 class Foo {
2406 int a;
2407 int b;
2408 int c;
2409 int d;
2410 int e;
2411 int f;
2412 int g;
2413 int h;
2414 int i;
2415 }
2416 Foo my_foo;
2417
2418Adding a simple filter:
2419
2420(lldb) type filter add --child a --child g Foo
2421(lldb) frame variable my_foo
2422
2423)"
2424 "Produces output where only a and g are displayed. Other children of my_foo \
2425(b, c, d, e, f, h and i) are available by asking for them explicitly:"
2426 R"(
2427
2428(lldb) frame variable my_foo.b my_foo.c my_foo.i
2429
2430)"
2431 "The formatting option --raw on frame variable bypasses the filter, showing \
2432all children of my_foo as if no filter was defined:"
2433 R"(
2435(lldb) frame variable my_foo --raw)");
2436 }
2438 ~CommandObjectTypeFilterAdd() override = default;
2439
2440protected:
2441 void DoExecute(Args &command, CommandReturnObject &result) override {
2442 const size_t argc = command.GetArgumentCount();
2443
2444 if (argc < 1) {
2445 result.AppendErrorWithFormat("%s takes one or more args.\n",
2446 m_cmd_name.c_str());
2447 return;
2448 }
2449
2450 if (m_options.m_expr_paths.empty()) {
2451 result.AppendErrorWithFormat("%s needs one or more children.\n",
2452 m_cmd_name.c_str());
2453 return;
2454 }
2455
2458 .SetCascades(m_options.m_cascade)
2462 // go through the expression paths
2464 end = m_options.m_expr_paths.end();
2466 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++)
2467 entry->AddExpressionPath(*begin);
2468
2469 // now I have a valid provider, let's add it to every type
2470
2471 lldb::TypeCategoryImplSP category;
2473 ConstString(m_options.m_category.c_str()), category);
2474
2475 Status error;
2476
2477 WarnOnPotentialUnquotedUnsignedType(command, result);
2478
2479 for (auto &arg_entry : command.entries()) {
2480 if (arg_entry.ref().empty()) {
2481 result.AppendError("empty typenames not allowed");
2482 return;
2483 }
2484
2485 ConstString typeCS(arg_entry.ref());
2486 if (!AddFilter(typeCS, entry,
2489 result.AppendError(error.AsCString());
2490 return;
2492 }
2493
2495 }
2496};
2497
2498// "type lookup"
2499#define LLDB_OPTIONS_type_lookup
2500#include "CommandOptions.inc"
2501
2503protected:
2504 // this function is allowed to do a more aggressive job at guessing languages
2505 // than the expression parser is comfortable with - so leave the original
2506 // call alone and add one that is specific to type lookup
2509
2510 if (!frame)
2511 return lang_type;
2512
2513 lang_type = frame->GuessLanguage().AsLanguageType();
2514 if (lang_type != lldb::eLanguageTypeUnknown)
2515 return lang_type;
2517 Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
2518 if (s)
2519 lang_type = s->GetMangled().GuessLanguage();
2521 return lang_type;
2522 }
2523
2524 class CommandOptions : public OptionGroup {
2525 public:
2526 CommandOptions() = default;
2527
2528 ~CommandOptions() override = default;
2529
2530 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2531 return llvm::ArrayRef(g_type_lookup_options);
2532 }
2533
2534 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
2535 ExecutionContext *execution_context) override {
2536 Status error;
2537
2538 const int short_option = g_type_lookup_options[option_idx].short_option;
2539
2540 switch (short_option) {
2541 case 'h':
2542 m_show_help = true;
2543 break;
2544
2545 case 'l':
2547 break;
2548
2549 default:
2550 llvm_unreachable("Unimplemented option");
2551 }
2552
2553 return error;
2554 }
2555
2556 void OptionParsingStarting(ExecutionContext *execution_context) override {
2557 m_show_help = false;
2559 }
2560
2561 // Options table: Required for subclasses of Options.
2562
2563 bool m_show_help = false;
2565 };
2566
2568 CommandOptions m_command_options;
2569
2570public:
2572 : CommandObjectRaw(interpreter, "type lookup",
2573 "Lookup types and declarations in the current target, "
2574 "following language-specific naming conventions.",
2575 "type lookup <type-specifier>",
2576 eCommandRequiresTarget) {
2579 }
2580
2581 ~CommandObjectTypeLookup() override = default;
2582
2583 Options *GetOptions() override { return &m_option_group; }
2584
2585 llvm::StringRef GetHelpLong() override {
2586 if (!m_cmd_help_long.empty())
2587 return m_cmd_help_long;
2588
2589 StreamString stream;
2590 Language::ForEach([&](Language *lang) {
2591 if (const char *help = lang->GetLanguageSpecificTypeLookupHelp())
2592 stream.Printf("%s\n", help);
2593 return true;
2594 });
2595
2596 m_cmd_help_long = std::string(stream.GetString());
2597 return m_cmd_help_long;
2598 }
2599
2600 void DoExecute(llvm::StringRef raw_command_line,
2601 CommandReturnObject &result) override {
2602 if (raw_command_line.empty()) {
2603 result.AppendError(
2604 "type lookup cannot be invoked without a type name as argument");
2605 return;
2606 }
2607
2608 auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
2610
2611 OptionsWithRaw args(raw_command_line);
2612 const char *name_of_type = args.GetRawPart().c_str();
2613
2614 if (args.HasArgs())
2615 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
2616 exe_ctx))
2617 return;
2618
2619 ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();
2620
2621 bool any_found = false;
2622
2623 std::vector<Language *> languages;
2624
2625 bool is_global_search = false;
2626 LanguageType guessed_language = lldb::eLanguageTypeUnknown;
2627
2628 if ((is_global_search =
2630 Language::ForEach([&](Language *lang) {
2631 languages.push_back(lang);
2632 return true;
2633 });
2634 } else {
2636 }
2637
2638 // This is not the most efficient way to do this, but we support very few
2639 // languages so the cost of the sort is going to be dwarfed by the actual
2640 // lookup anyway
2642 guessed_language = GuessLanguage(frame);
2643 if (guessed_language != eLanguageTypeUnknown) {
2644 llvm::sort(
2645 languages.begin(), languages.end(),
2646 [guessed_language](Language *lang1, Language *lang2) -> bool {
2647 if (!lang1 || !lang2)
2648 return false;
2649 LanguageType lt1 = lang1->GetLanguageType();
2650 LanguageType lt2 = lang2->GetLanguageType();
2651 if (lt1 == lt2)
2652 return false;
2653 if (lt1 == guessed_language)
2654 return true; // make the selected frame's language come first
2655 if (lt2 == guessed_language)
2656 return false; // make the selected frame's language come first
2657 return (lt1 < lt2); // normal comparison otherwise
2658 });
2659 }
2660 }
2662 bool is_first_language = true;
2663
2664 for (Language *language : languages) {
2665 if (!language)
2666 continue;
2667
2668 if (auto scavenger = language->GetTypeScavenger()) {
2670 if (scavenger->Find(best_scope, name_of_type, search_results) > 0) {
2671 for (const auto &search_result : search_results) {
2672 if (search_result && search_result->IsValid()) {
2673 any_found = true;
2674 search_result->DumpToStream(result.GetOutputStream(),
2675 this->m_command_options.m_show_help);
2676 }
2677 }
2678 }
2679 }
2680 // this is "type lookup SomeName" and we did find a match, so get out
2681 if (any_found && is_global_search)
2682 break;
2683 else if (is_first_language && is_global_search &&
2684 guessed_language != lldb::eLanguageTypeUnknown) {
2685 is_first_language = false;
2686 result.GetOutputStream().Printf(
2687 "no type was found in the current language %s matching '%s'; "
2688 "performing a global search across all languages\n",
2689 Language::GetNameForLanguageType(guessed_language), name_of_type);
2690 }
2691 }
2692
2693 if (!any_found)
2694 result.AppendMessageWithFormat("no type was found matching '%s'\n",
2695 name_of_type);
2696
2699 }
2700};
2701
2702template <typename FormatterType>
2704public:
2705 typedef std::function<typename FormatterType::SharedPointer(ValueObject &)>
2708 const char *formatter_name,
2709 DiscoveryFunction discovery_func)
2710 : CommandObjectRaw(interpreter, "", "", "", eCommandRequiresFrame),
2711 m_formatter_name(formatter_name ? formatter_name : ""),
2712 m_discovery_function(discovery_func) {
2713 StreamString name;
2714 name.Printf("type %s info", formatter_name);
2715 SetCommandName(name.GetString());
2716 StreamString help;
2717 help.Printf("This command evaluates the provided expression and shows "
2718 "which %s is applied to the resulting value (if any).",
2719 formatter_name);
2720 SetHelp(help.GetString());
2721 StreamString syntax;
2722 syntax.Printf("type %s info <expr>", formatter_name);
2723 SetSyntax(syntax.GetString());
2724 }
2725
2726 ~CommandObjectFormatterInfo() override = default;
2727
2728protected:
2729 void DoExecute(llvm::StringRef command,
2730 CommandReturnObject &result) override {
2731 TargetSP target_sp = GetDebugger().GetSelectedTarget();
2732 Thread *thread = GetDefaultThread();
2733 if (!thread) {
2734 result.AppendError("no default thread");
2735 return;
2737
2738 StackFrameSP frame_sp =
2740 ValueObjectSP result_valobj_sp;
2742 lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(
2743 command, frame_sp.get(), result_valobj_sp, options);
2744 if (expr_result == eExpressionCompleted && result_valobj_sp) {
2745 result_valobj_sp =
2746 result_valobj_sp->GetQualifiedRepresentationIfAvailable(
2747 target_sp->GetPreferDynamicValue(),
2748 target_sp->GetEnableSyntheticValue());
2749 typename FormatterType::SharedPointer formatter_sp =
2750 m_discovery_function(*result_valobj_sp);
2751 if (formatter_sp) {
2752 std::string description(formatter_sp->GetDescription());
2753 result.GetOutputStream()
2754 << m_formatter_name << " applied to ("
2755 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2756 << ") " << command << " is: " << description << "\n";
2758 } else {
2759 result.GetOutputStream()
2760 << "no " << m_formatter_name << " applies to ("
2761 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>")
2762 << ") " << command << "\n";
2764 }
2765 } else {
2766 result.AppendError("failed to evaluate expression");
2767 }
2768 }
2769
2770private:
2771 std::string m_formatter_name;
2773};
2774
2776public:
2779 interpreter, "type format",
2780 "Commands for customizing value display formats.",
2781 "type format [<sub-command-options>] ") {
2783 "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter)));
2785 new CommandObjectTypeFormatClear(interpreter)));
2787 interpreter)));
2789 "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter)));
2792 interpreter, "format",
2794 return valobj.GetValueFormat();
2795 })));
2796 }
2797
2798 ~CommandObjectTypeFormat() override = default;
2799};
2800
2802public:
2805 interpreter, "type synthetic",
2806 "Commands for operating on synthetic type representations.",
2807 "type synthetic [<sub-command-options>] ") {
2808 LoadSubCommand("add",
2811 "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter)));
2813 interpreter)));
2815 "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter)));
2817 "info",
2819 interpreter, "synthetic",
2821 return valobj.GetSyntheticChildren();
2822 })));
2823 }
2824
2825 ~CommandObjectTypeSynth() override = default;
2826};
2827
2829public:
2831 : CommandObjectMultiword(interpreter, "type filter",
2832 "Commands for operating on type filters.",
2833 "type filter [<sub-command-options>] ") {
2837 new CommandObjectTypeFilterClear(interpreter)));
2839 interpreter)));
2841 "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter)));
2842 }
2843
2844 ~CommandObjectTypeFilter() override = default;
2845};
2846
2848public:
2850 : CommandObjectMultiword(interpreter, "type category",
2851 "Commands for operating on type categories.",
2852 "type category [<sub-command-options>] ") {
2854 "define",
2857 "enable",
2860 "disable",
2863 "delete",
2866 new CommandObjectTypeCategoryList(interpreter)));
2867 }
2868
2869 ~CommandObjectTypeCategory() override = default;
2870};
2871
2873public:
2876 interpreter, "type summary",
2877 "Commands for editing variable summary display options.",
2878 "type summary [<sub-command-options>] ") {
2880 "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter)));
2882 interpreter)));
2884 interpreter)));
2886 "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter)));
2889 interpreter, "summary",
2891 return valobj.GetSummaryFormat();
2892 })));
2893 }
2894
2895 ~CommandObjectTypeSummary() override = default;
2896};
2897
2898// CommandObjectType
2899
2901 : CommandObjectMultiword(interpreter, "type",
2902 "Commands for operating on the type system.",
2903 "type [<sub-command-options>]") {
2904 LoadSubCommand("category",
2905 CommandObjectSP(new CommandObjectTypeCategory(interpreter)));
2906 LoadSubCommand("filter",
2907 CommandObjectSP(new CommandObjectTypeFilter(interpreter)));
2908 LoadSubCommand("format",
2909 CommandObjectSP(new CommandObjectTypeFormat(interpreter)));
2910 LoadSubCommand("summary",
2911 CommandObjectSP(new CommandObjectTypeSummary(interpreter)));
2912 LoadSubCommand("synthetic",
2913 CommandObjectSP(new CommandObjectTypeSynth(interpreter)));
2914 LoadSubCommand("lookup",
2915 CommandObjectSP(new CommandObjectTypeLookup(interpreter)));
2916}
2917
2919
static const char * g_synth_addreader_instructions
static bool WarnOnPotentialUnquotedUnsignedType(Args &command, CommandReturnObject &result)
const char * FormatCategoryToString(FormatCategoryItem item, bool long_name)
static bool FixArrayTypeNameWithRegex(ConstString &type_name)
static llvm::raw_ostream & error(Stream &strm)
~CommandObjectFormatterInfo() override=default
DiscoveryFunction m_discovery_function
void DoExecute(llvm::StringRef command, CommandReturnObject &result) override
std::function< typename FormatterType::SharedPointer(ValueObject &)> DiscoveryFunction
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
void OptionParsingStarting(ExecutionContext *execution_context) override
~CommandObjectTypeCategoryDefine() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectTypeCategoryDelete() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
void OptionParsingStarting(ExecutionContext *execution_context) override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
void DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectTypeCategoryDisable() override=default
void OptionParsingStarting(ExecutionContext *execution_context) override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
void DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectTypeCategoryEnable() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The default version handles argument definitions that have only one argument type,...
~CommandObjectTypeCategoryList() override=default
~CommandObjectTypeCategory() override=default
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
void OptionParsingStarting(ExecutionContext *execution_context) override
~CommandObjectTypeFilterAdd() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
Options * GetOptions() override
bool AddFilter(ConstString type_name, TypeFilterImplSP entry, FilterFormatType type, std::string category_name, Status *error)
~CommandObjectTypeFilterDelete() override=default
~CommandObjectTypeFilter() override=default
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, ExecutionContext *execution_context) override
void OptionParsingStarting(ExecutionContext *execution_context) override
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
Options * GetOptions() override
CommandObjectTypeFormatAdd(CommandInterpreter &interpreter)
OptionGroupOptions m_option_group
OptionGroupFormat m_format_options
~CommandObjectTypeFormatAdd() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
CommandObjectTypeFormatClear(CommandInterpreter &interpreter)
CommandObjectTypeFormatDelete(CommandInterpreter &interpreter)
~CommandObjectTypeFormatDelete() override=default
CommandObjectTypeFormatList(CommandInterpreter &interpreter)
~CommandObjectTypeFormat() override=default
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
void OptionParsingStarting(ExecutionContext *execution_context) override
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
CommandObjectTypeFormatterClear(CommandInterpreter &interpreter, FormatCategoryItem formatter_kind, const char *name, const char *help)
~CommandObjectTypeFormatterClear() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
void OptionParsingStarting(ExecutionContext *execution_context) override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
static constexpr const char * g_long_help_template
virtual bool FormatterSpecificDeletion(ConstString typeCS)
static constexpr const char * g_short_help_template
~CommandObjectTypeFormatterDelete() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The default version handles argument definitions that have only one argument type,...
CommandObjectTypeFormatterDelete(CommandInterpreter &interpreter, FormatCategoryItem formatter_kind)
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
void OptionParsingStarting(ExecutionContext *execution_context) override
void DoExecute(Args &command, CommandReturnObject &result) override
FormatterType::SharedPointer FormatterSharedPointer
virtual bool FormatterSpecificList(CommandReturnObject &result)
static bool ShouldListItem(llvm::StringRef s, RegularExpression *regex)
CommandObjectTypeFormatterList(CommandInterpreter &interpreter, const char *name, const char *help)
~CommandObjectTypeFormatterList() override=default
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
void OptionParsingStarting(ExecutionContext *execution_context) override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, ExecutionContext *execution_context) override
OptionGroupOptions m_option_group
void DoExecute(llvm::StringRef raw_command_line, CommandReturnObject &result) override
lldb::LanguageType GuessLanguage(StackFrame *frame)
~CommandObjectTypeLookup() override=default
llvm::StringRef GetHelpLong() override
Options * GetOptions() override
void OptionParsingStarting(ExecutionContext *execution_context) override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
CommandOptions(CommandInterpreter &interpreter)
~CommandObjectTypeSummaryAdd() override=default
Options * GetOptions() override
bool Execute_ScriptSummary(Args &command, CommandReturnObject &result)
void DoExecute(Args &command, CommandReturnObject &result) override
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override
bool Execute_StringSummary(Args &command, CommandReturnObject &result)
CommandObjectTypeSummaryAdd(CommandInterpreter &interpreter)
void IOHandlerInputComplete(IOHandler &io_handler, std::string &data) override
Called when a line or lines have been retrieved.
bool AddNamedSummary(ConstString summary_name, lldb::TypeSummaryImplSP entry, Status *error=nullptr)
bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry, FormatterMatchType match_type, std::string category, Status *error=nullptr)
~CommandObjectTypeSummaryDelete() override=default
bool FormatterSpecificDeletion(ConstString typeCS) override
bool FormatterSpecificList(CommandReturnObject &result) override
~CommandObjectTypeSummary() override=default
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
void OptionParsingStarting(ExecutionContext *execution_context) override
void IOHandlerInputComplete(IOHandler &io_handler, std::string &data) override
Called when a line or lines have been retrieved.
CommandObjectTypeSynthAdd(CommandInterpreter &interpreter)
bool Execute_PythonClass(Args &command, CommandReturnObject &result)
bool AddSynth(ConstString type_name, lldb::SyntheticChildrenSP entry, FormatterMatchType match_type, std::string category_name, Status *error)
Options * GetOptions() override
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override
void DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectTypeSynthAdd() override=default
bool Execute_HandwritePython(Args &command, CommandReturnObject &result)
~CommandObjectTypeSynthDelete() override=default
~CommandObjectTypeSynth() override=default
std::shared_ptr< ScriptAddOptions > SharedPointer
TypeSummaryImpl::Flags m_flags
ScriptAddOptions(const TypeSummaryImpl::Flags &flags, FormatterMatchType match_type, ConstString name, std::string catg)
FormatterMatchType m_match_type
std::string m_category
FormatterMatchType m_match_type
StringList m_target_types
std::shared_ptr< SynthAddOptions > SharedPointer
SynthAddOptions(bool sptr, bool sref, bool casc, FormatterMatchType match_type, std::string catg)
A command line argument class.
Definition: Args.h:33
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.h:120
llvm::ArrayRef< ArgEntry > entries() const
Definition: Args.h:132
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
Definition: Args.cpp:273
bool empty() const
Definition: Args.h:122
static bool InvokeCommonCompletionCallbacks(CommandInterpreter &interpreter, uint32_t completion_mask, lldb_private::CompletionRequest &request, SearchFilter *searcher)
ExecutionContext GetExecutionContext() const
void GetPythonCommandsFromIOHandler(const char *prompt, IOHandlerDelegate &delegate, void *baton=nullptr)
bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override
CommandObjectType(CommandInterpreter &interpreter)
virtual void SetHelpLong(llvm::StringRef str)
void AddSimpleArgumentList(lldb::CommandArgumentType arg_type, ArgumentRepetitionType repetition_type=eArgRepeatPlain)
bool ParseOptionsAndNotify(Args &args, CommandReturnObject &result, OptionGroupOptions &group_options, ExecutionContext &exe_ctx)
ExecutionContext m_exe_ctx
CommandInterpreter & GetCommandInterpreter()
CommandInterpreter & m_interpreter
void SetSyntax(llvm::StringRef str)
void SetCommandName(llvm::StringRef name)
virtual void SetHelp(llvm::StringRef str)
void void AppendError(llvm::StringRef in_string)
void AppendWarningWithFormat(const char *format,...) __attribute__((format(printf
void SetStatus(lldb::ReturnStatus status)
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
void AppendMessageWithFormat(const char *format,...) __attribute__((format(printf
void void AppendWarning(llvm::StringRef in_string)
"lldb/Utility/ArgCompletionRequest.h"
A uniqued constant string class.
Definition: ConstString.h:40
void SetCString(const char *cstr)
Set the C string value.
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:188
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:197
void SetString(llvm::StringRef s)
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:216
static bool Delete(ConstString category)
static void Disable(ConstString category)
static void ForEach(TypeCategoryMap::ForEachCallback callback)
static void Enable(ConstString category, TypeCategoryMap::Position=TypeCategoryMap::Default)
static bool GetCategory(ConstString category, lldb::TypeCategoryImplSP &entry, bool allow_create=true)
static void Add(ConstString type, const lldb::TypeSummaryImplSP &entry)
static void ForEach(std::function< bool(const TypeMatcher &, const lldb::TypeSummaryImplSP &)> callback)
lldb::TargetSP GetSelectedTarget()
Definition: Debugger.h:185
ScriptInterpreter * GetScriptInterpreter(bool can_create=true, std::optional< lldb::ScriptLanguage > language={})
Definition: Debugger.cpp:1719
"lldb/Target/ExecutionContextScope.h" Inherit from this if your object can reconstruct its execution ...
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
StackFrame * GetFramePtr() const
Returns a pointer to the frame object.
ValueType Clear(ValueType mask=~static_cast< ValueType >(0))
Clear one or more flags.
Definition: Flags.h:61
lldb::StreamFileSP GetErrorStreamFileSP()
Definition: IOHandler.cpp:107
lldb::StreamFileSP GetOutputStreamFileSP()
Definition: IOHandler.cpp:105
void SetIsDone(bool b)
Definition: IOHandler.h:85
std::set< std::unique_ptr< Result > > ResultSet
Definition: Language.h:52
static Language * FindPlugin(lldb::LanguageType language)
Definition: Language.cpp:84
static const char * GetNameForLanguageType(lldb::LanguageType language)
Definition: Language.cpp:266
virtual const char * GetLanguageSpecificTypeLookupHelp()
Definition: Language.cpp:440
static lldb::LanguageType GetLanguageTypeFromString(const char *string)=delete
static void ForEach(std::function< bool(Language *)> callback)
Definition: Language.cpp:131
lldb::LanguageType GuessLanguage() const
Try to guess the language from the mangling.
Definition: Mangled.cpp:391
static const uint32_t OPTION_GROUP_FORMAT
void Append(OptionGroup *group)
Append options from a OptionGroup class.
Definition: Options.cpp:788
Status SetValueFromString(llvm::StringRef value, VarSetOperationType op=eVarSetOperationAssign) override
lldb::LanguageType GetCurrentValue() const
Status SetValueFromString(llvm::StringRef value, VarSetOperationType op=eVarSetOperationAssign) override
llvm::StringRef GetCurrentValueAsRef() const
Status SetCurrentValue(llvm::StringRef value)
A pair of an option list with a 'raw' string as a suffix.
Definition: Args.h:319
A command line option parsing protocol class.
Definition: Options.h:58
void NotifyOptionParsingStarting(ExecutionContext *execution_context)
Definition: Options.cpp:68
std::vector< Option > m_getopt_table
Definition: Options.h:198
bool Execute(llvm::StringRef string, llvm::SmallVectorImpl< llvm::StringRef > *matches=nullptr) const
Execute a regular expression match using the compiled regular expression that is already in this obje...
llvm::StringRef GetText() const
Access the regular expression text.
virtual bool GenerateTypeScriptFunction(const char *oneliner, std::string &output, const void *name_token=nullptr)
virtual bool GenerateTypeSynthClass(StringList &input, std::string &output, const void *name_token=nullptr)
virtual bool CheckObjectExists(const char *name)
This base class provides an interface to stack frames.
Definition: StackFrame.h:44
SourceLanguage GuessLanguage()
Similar to GetLanguage(), but is allowed to take a potentially incorrect guess if exact information i...
const SymbolContext & GetSymbolContext(lldb::SymbolContextItem resolve_scope)
Provide a SymbolContext for this StackFrame's current pc value.
Definition: StackFrame.cpp:301
An error handling class.
Definition: Status.h:118
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition: Status.cpp:106
static Status FromErrorString(const char *str)
Definition: Status.h:141
const char * GetData() const
Definition: StreamString.h:45
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:65
std::string CopyList(const char *item_preamble=nullptr, const char *items_sep="\n") const
Definition: StringList.cpp:198
size_t SplitIntoLines(const std::string &lines)
Definition: StringList.cpp:152
size_t GetSize() const
Definition: StringList.cpp:74
Symbol * symbol
The Symbol for a given query.
Mangled & GetMangled()
Definition: Symbol.h:146
Flags & SetSkipReferences(bool value=true)
Flags & SetSkipPointers(bool value=true)
std::shared_ptr< SyntheticChildren > SharedPointer
lldb::StackFrameSP GetSelectedFrame(SelectMostRelevant select_most_relevant)
Definition: Thread.cpp:271
static const Position Default
Flags & SetCascades(bool value=true)
Definition: TypeFormat.h:55
Flags & SetSkipReferences(bool value=true)
Definition: TypeFormat.h:81
Flags & SetSkipPointers(bool value=true)
Definition: TypeFormat.h:68
std::shared_ptr< TypeFormatImpl > SharedPointer
Definition: TypeFormat.h:112
Class for matching type names.
ConstString GetMatchString() const
Returns the underlying match string for this TypeMatcher.
Flags & SetCascades(bool value=true)
Definition: TypeSummary.h:86
Flags & SetHideEmptyAggregates(bool value=true)
Definition: TypeSummary.h:138
Flags & SetSkipPointers(bool value=true)
Definition: TypeSummary.h:99
Flags & SetHideItemNames(bool value=true)
Definition: TypeSummary.h:177
Flags & SetDontShowChildren(bool value=true)
Definition: TypeSummary.h:125
Flags & SetSkipReferences(bool value=true)
Definition: TypeSummary.h:112
Flags & SetShowMembersOneLiner(bool value=true)
Definition: TypeSummary.h:164
Flags & SetDontShowValue(bool value=true)
Definition: TypeSummary.h:151
std::shared_ptr< TypeSummaryImpl > SharedPointer
Definition: TypeSummary.h:275
lldb::TypeFormatImplSP GetValueFormat()
Definition: ValueObject.h:807
lldb::TypeSummaryImplSP GetSummaryFormat()
Definition: ValueObject.h:788
lldb::SyntheticChildrenSP GetSyntheticChildren()
Definition: ValueObject.h:819
#define LLDB_OPT_SET_1
Definition: lldb-defines.h:111
@ DoNoSelectMostRelevantFrame
A class that represents a running process on the host machine.
std::vector< OptionArgElement > OptionElementVector
Definition: Options.h:43
FormatCategoryItem
Format category entry types.
Definition: SBAddress.h:15
@ eTypeCategoryNameCompletion
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
Definition: lldb-forward.h:424
std::shared_ptr< lldb_private::TypeSummaryImpl > TypeSummaryImplSP
Definition: lldb-forward.h:475
std::shared_ptr< lldb_private::CommandObject > CommandObjectSP
Definition: lldb-forward.h:333
std::shared_ptr< lldb_private::TypeFormatImpl > TypeFormatImplSP
Definition: lldb-forward.h:472
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Definition: lldb-forward.h:484
Format
Display format definitions.
LanguageType
Programming language type.
@ eLanguageTypeUnknown
Unknown or invalid language value.
FormatterMatchType
Type of match to be performed when looking for a formatter for a data type.
@ eFormatterMatchExact
@ eFormatterMatchRegex
@ eFormatterMatchCallback
ExpressionResults
The results of expression evaluation.
@ eExpressionCompleted
@ eReturnStatusSuccessFinishResult
@ eReturnStatusSuccessFinishNoResult
std::shared_ptr< lldb_private::StreamFile > StreamFileSP
Definition: lldb-forward.h:433
std::shared_ptr< lldb_private::SyntheticChildren > SyntheticChildrenSP
Definition: lldb-forward.h:445
std::shared_ptr< lldb_private::TypeCategoryImpl > TypeCategoryImplSP
Definition: lldb-forward.h:463
std::shared_ptr< lldb_private::TypeFilterImpl > TypeFilterImplSP
Definition: lldb-forward.h:468
std::shared_ptr< lldb_private::Target > TargetSP
Definition: lldb-forward.h:448
static bool ToBoolean(llvm::StringRef s, bool fail_value, bool *success_ptr)
lldb::LanguageType AsLanguageType() const
Definition: Language.cpp:554