1 //===-- CommandObjectType.cpp -----------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "CommandObjectType.h" 11 12 // C Includes 13 // C++ Includes 14 #include <cctype> 15 #include <functional> 16 17 // Other libraries and framework includes 18 #include "llvm/ADT/StringRef.h" 19 20 // Project includes 21 #include "lldb/Core/ConstString.h" 22 #include "lldb/Core/Debugger.h" 23 #include "lldb/Core/IOHandler.h" 24 #include "lldb/Core/RegularExpression.h" 25 #include "lldb/Core/State.h" 26 #include "lldb/Core/StringList.h" 27 #include "lldb/DataFormatters/DataVisualization.h" 28 #include "lldb/Interpreter/CommandInterpreter.h" 29 #include "lldb/Interpreter/CommandObject.h" 30 #include "lldb/Interpreter/CommandReturnObject.h" 31 #include "lldb/Interpreter/Options.h" 32 #include "lldb/Interpreter/OptionGroupFormat.h" 33 #include "lldb/Interpreter/OptionValueBoolean.h" 34 #include "lldb/Interpreter/OptionValueLanguage.h" 35 #include "lldb/Interpreter/OptionValueString.h" 36 #include "lldb/Target/Language.h" 37 #include "lldb/Target/Process.h" 38 #include "lldb/Target/StackFrame.h" 39 #include "lldb/Target/Target.h" 40 #include "lldb/Target/Thread.h" 41 #include "lldb/Target/ThreadList.h" 42 43 using namespace lldb; 44 using namespace lldb_private; 45 46 class ScriptAddOptions 47 { 48 public: 49 TypeSummaryImpl::Flags m_flags; 50 StringList m_target_types; 51 bool m_regex; 52 ConstString m_name; 53 std::string m_category; 54 55 ScriptAddOptions(const TypeSummaryImpl::Flags& flags, 56 bool regx, 57 const ConstString& name, 58 std::string catg) : 59 m_flags(flags), 60 m_regex(regx), 61 m_name(name), 62 m_category(catg) 63 { 64 } 65 66 typedef std::shared_ptr<ScriptAddOptions> SharedPointer; 67 }; 68 69 class SynthAddOptions 70 { 71 public: 72 bool m_skip_pointers; 73 bool m_skip_references; 74 bool m_cascade; 75 bool m_regex; 76 StringList m_target_types; 77 std::string m_category; 78 79 SynthAddOptions(bool sptr, 80 bool sref, 81 bool casc, 82 bool regx, 83 std::string catg) : 84 m_skip_pointers(sptr), 85 m_skip_references(sref), 86 m_cascade(casc), 87 m_regex(regx), 88 m_target_types(), 89 m_category(catg) 90 { 91 } 92 93 typedef std::shared_ptr<SynthAddOptions> SharedPointer; 94 }; 95 96 static bool 97 WarnOnPotentialUnquotedUnsignedType (Args& command, CommandReturnObject &result) 98 { 99 for (unsigned idx = 0; idx < command.GetArgumentCount(); idx++) 100 { 101 const char* arg = command.GetArgumentAtIndex(idx); 102 if (idx+1 < command.GetArgumentCount()) 103 { 104 if (arg && 0 == strcmp(arg,"unsigned")) 105 { 106 const char* next = command.GetArgumentAtIndex(idx+1); 107 if (next && 108 (0 == strcmp(next, "int") || 109 0 == strcmp(next, "short") || 110 0 == strcmp(next, "char") || 111 0 == strcmp(next, "long"))) 112 { 113 result.AppendWarningWithFormat("%s %s being treated as two types. if you meant the combined type name use quotes, as in \"%s %s\"\n", 114 arg,next,arg,next); 115 return true; 116 } 117 } 118 } 119 } 120 return false; 121 } 122 123 class CommandObjectTypeSummaryAdd : 124 public CommandObjectParsed, 125 public IOHandlerDelegateMultiline 126 { 127 private: 128 class CommandOptions : public Options 129 { 130 public: 131 CommandOptions (CommandInterpreter &interpreter) : 132 Options (interpreter) 133 { 134 } 135 136 ~CommandOptions() override = default; 137 138 Error 139 SetOptionValue (uint32_t option_idx, const char *option_arg) override; 140 141 void 142 OptionParsingStarting () override; 143 144 const OptionDefinition* 145 GetDefinitions () override 146 { 147 return g_option_table; 148 } 149 150 // Options table: Required for subclasses of Options. 151 152 static OptionDefinition g_option_table[]; 153 154 // Instance variables to hold the values for command options. 155 156 TypeSummaryImpl::Flags m_flags; 157 bool m_regex; 158 std::string m_format_string; 159 ConstString m_name; 160 std::string m_python_script; 161 std::string m_python_function; 162 bool m_is_add_script; 163 std::string m_category; 164 }; 165 166 CommandOptions m_options; 167 168 Options * 169 GetOptions () override 170 { 171 return &m_options; 172 } 173 174 bool 175 Execute_ScriptSummary (Args& command, CommandReturnObject &result); 176 177 bool 178 Execute_StringSummary (Args& command, CommandReturnObject &result); 179 180 public: 181 enum SummaryFormatType 182 { 183 eRegularSummary, 184 eRegexSummary, 185 eNamedSummary 186 }; 187 188 CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter); 189 190 ~CommandObjectTypeSummaryAdd() override = default; 191 192 void 193 IOHandlerActivated (IOHandler &io_handler) override 194 { 195 static const char *g_summary_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" 196 "def function (valobj,internal_dict):\n" 197 " \"\"\"valobj: an SBValue which you want to provide a summary for\n" 198 " internal_dict: an LLDB support object not to be used\"\"\"\n"; 199 200 StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 201 if (output_sp) 202 { 203 output_sp->PutCString(g_summary_addreader_instructions); 204 output_sp->Flush(); 205 } 206 } 207 208 void 209 IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override 210 { 211 StreamFileSP error_sp = io_handler.GetErrorStreamFile(); 212 213 #ifndef LLDB_DISABLE_PYTHON 214 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 215 if (interpreter) 216 { 217 StringList lines; 218 lines.SplitIntoLines(data); 219 if (lines.GetSize() > 0) 220 { 221 ScriptAddOptions *options_ptr = ((ScriptAddOptions*)io_handler.GetUserData()); 222 if (options_ptr) 223 { 224 ScriptAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope 225 226 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 227 if (interpreter) 228 { 229 std::string funct_name_str; 230 if (interpreter->GenerateTypeScriptFunction (lines, funct_name_str)) 231 { 232 if (funct_name_str.empty()) 233 { 234 error_sp->Printf ("unable to obtain a valid function name from the script interpreter.\n"); 235 error_sp->Flush(); 236 } 237 else 238 { 239 // now I have a valid function name, let's add this as script for every type in the list 240 241 TypeSummaryImplSP script_format; 242 script_format.reset(new ScriptSummaryFormat(options->m_flags, 243 funct_name_str.c_str(), 244 lines.CopyList(" ").c_str())); 245 246 Error error; 247 248 for (size_t i = 0; i < options->m_target_types.GetSize(); i++) 249 { 250 const char *type_name = options->m_target_types.GetStringAtIndex(i); 251 CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name), 252 script_format, 253 (options->m_regex ? CommandObjectTypeSummaryAdd::eRegexSummary : CommandObjectTypeSummaryAdd::eRegularSummary), 254 options->m_category, 255 &error); 256 if (error.Fail()) 257 { 258 error_sp->Printf ("error: %s", error.AsCString()); 259 error_sp->Flush(); 260 } 261 } 262 263 if (options->m_name) 264 { 265 CommandObjectTypeSummaryAdd::AddSummary (options->m_name, 266 script_format, 267 CommandObjectTypeSummaryAdd::eNamedSummary, 268 options->m_category, 269 &error); 270 if (error.Fail()) 271 { 272 CommandObjectTypeSummaryAdd::AddSummary (options->m_name, 273 script_format, 274 CommandObjectTypeSummaryAdd::eNamedSummary, 275 options->m_category, 276 &error); 277 if (error.Fail()) 278 { 279 error_sp->Printf ("error: %s", error.AsCString()); 280 error_sp->Flush(); 281 } 282 } 283 else 284 { 285 error_sp->Printf ("error: %s", error.AsCString()); 286 error_sp->Flush(); 287 } 288 } 289 else 290 { 291 if (error.AsCString()) 292 { 293 error_sp->Printf ("error: %s", error.AsCString()); 294 error_sp->Flush(); 295 } 296 } 297 } 298 } 299 else 300 { 301 error_sp->Printf ("error: unable to generate a function.\n"); 302 error_sp->Flush(); 303 } 304 } 305 else 306 { 307 error_sp->Printf ("error: no script interpreter.\n"); 308 error_sp->Flush(); 309 } 310 } 311 else 312 { 313 error_sp->Printf ("error: internal synchronization information missing or invalid.\n"); 314 error_sp->Flush(); 315 } 316 } 317 else 318 { 319 error_sp->Printf ("error: empty function, didn't add python command.\n"); 320 error_sp->Flush(); 321 } 322 } 323 else 324 { 325 error_sp->Printf ("error: script interpreter missing, didn't add python command.\n"); 326 error_sp->Flush(); 327 } 328 #endif // LLDB_DISABLE_PYTHON 329 io_handler.SetIsDone(true); 330 } 331 332 static bool 333 AddSummary(ConstString type_name, 334 lldb::TypeSummaryImplSP entry, 335 SummaryFormatType type, 336 std::string category, 337 Error* error = nullptr); 338 339 protected: 340 bool 341 DoExecute (Args& command, CommandReturnObject &result) override; 342 }; 343 344 static const char *g_synth_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" 345 "You must define a Python class with these methods:\n" 346 " def __init__(self, valobj, dict):\n" 347 " def num_children(self):\n" 348 " def get_child_at_index(self, index):\n" 349 " def get_child_index(self, name):\n" 350 " def update(self):\n" 351 " '''Optional'''\n" 352 "class synthProvider:\n"; 353 354 class CommandObjectTypeSynthAdd : 355 public CommandObjectParsed, 356 public IOHandlerDelegateMultiline 357 { 358 private: 359 class CommandOptions : public Options 360 { 361 public: 362 CommandOptions (CommandInterpreter &interpreter) : 363 Options (interpreter) 364 { 365 } 366 367 ~CommandOptions() override = default; 368 369 Error 370 SetOptionValue (uint32_t option_idx, const char *option_arg) override 371 { 372 Error error; 373 const int short_option = m_getopt_table[option_idx].val; 374 bool success; 375 376 switch (short_option) 377 { 378 case 'C': 379 m_cascade = Args::StringToBoolean(option_arg, true, &success); 380 if (!success) 381 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg); 382 break; 383 case 'P': 384 handwrite_python = true; 385 break; 386 case 'l': 387 m_class_name = std::string(option_arg); 388 is_class_based = true; 389 break; 390 case 'p': 391 m_skip_pointers = true; 392 break; 393 case 'r': 394 m_skip_references = true; 395 break; 396 case 'w': 397 m_category = std::string(option_arg); 398 break; 399 case 'x': 400 m_regex = true; 401 break; 402 default: 403 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 404 break; 405 } 406 407 return error; 408 } 409 410 void 411 OptionParsingStarting () override 412 { 413 m_cascade = true; 414 m_class_name = ""; 415 m_skip_pointers = false; 416 m_skip_references = false; 417 m_category = "default"; 418 is_class_based = false; 419 handwrite_python = false; 420 m_regex = false; 421 } 422 423 const OptionDefinition* 424 GetDefinitions () override 425 { 426 return g_option_table; 427 } 428 429 // Options table: Required for subclasses of Options. 430 431 static OptionDefinition g_option_table[]; 432 433 // Instance variables to hold the values for command options. 434 435 bool m_cascade; 436 bool m_skip_references; 437 bool m_skip_pointers; 438 std::string m_class_name; 439 bool m_input_python; 440 std::string m_category; 441 bool is_class_based; 442 bool handwrite_python; 443 bool m_regex; 444 }; 445 446 CommandOptions m_options; 447 448 Options * 449 GetOptions () override 450 { 451 return &m_options; 452 } 453 454 bool 455 Execute_HandwritePython (Args& command, CommandReturnObject &result); 456 457 bool 458 Execute_PythonClass (Args& command, CommandReturnObject &result); 459 460 protected: 461 bool 462 DoExecute (Args& command, CommandReturnObject &result) override 463 { 464 WarnOnPotentialUnquotedUnsignedType(command, result); 465 466 if (m_options.handwrite_python) 467 return Execute_HandwritePython(command, result); 468 else if (m_options.is_class_based) 469 return Execute_PythonClass(command, result); 470 else 471 { 472 result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line"); 473 result.SetStatus(eReturnStatusFailed); 474 return false; 475 } 476 } 477 478 void 479 IOHandlerActivated (IOHandler &io_handler) override 480 { 481 StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 482 if (output_sp) 483 { 484 output_sp->PutCString(g_synth_addreader_instructions); 485 output_sp->Flush(); 486 } 487 } 488 489 void 490 IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override 491 { 492 StreamFileSP error_sp = io_handler.GetErrorStreamFile(); 493 494 #ifndef LLDB_DISABLE_PYTHON 495 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 496 if (interpreter) 497 { 498 StringList lines; 499 lines.SplitIntoLines(data); 500 if (lines.GetSize() > 0) 501 { 502 SynthAddOptions *options_ptr = ((SynthAddOptions*)io_handler.GetUserData()); 503 if (options_ptr) 504 { 505 SynthAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope 506 507 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 508 if (interpreter) 509 { 510 std::string class_name_str; 511 if (interpreter->GenerateTypeSynthClass (lines, class_name_str)) 512 { 513 if (class_name_str.empty()) 514 { 515 error_sp->Printf ("error: unable to obtain a proper name for the class.\n"); 516 error_sp->Flush(); 517 } 518 else 519 { 520 // everything should be fine now, let's add the synth provider class 521 522 SyntheticChildrenSP synth_provider; 523 synth_provider.reset(new ScriptedSyntheticChildren(SyntheticChildren::Flags().SetCascades(options->m_cascade). 524 SetSkipPointers(options->m_skip_pointers). 525 SetSkipReferences(options->m_skip_references), 526 class_name_str.c_str())); 527 528 529 lldb::TypeCategoryImplSP category; 530 DataVisualization::Categories::GetCategory(ConstString(options->m_category.c_str()), category); 531 532 Error error; 533 534 for (size_t i = 0; i < options->m_target_types.GetSize(); i++) 535 { 536 const char *type_name = options->m_target_types.GetStringAtIndex(i); 537 ConstString const_type_name(type_name); 538 if (const_type_name) 539 { 540 if (!CommandObjectTypeSynthAdd::AddSynth(const_type_name, 541 synth_provider, 542 options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth, 543 options->m_category, 544 &error)) 545 { 546 error_sp->Printf("error: %s\n", error.AsCString()); 547 error_sp->Flush(); 548 break; 549 } 550 } 551 else 552 { 553 error_sp->Printf ("error: invalid type name.\n"); 554 error_sp->Flush(); 555 break; 556 } 557 } 558 } 559 } 560 else 561 { 562 error_sp->Printf ("error: unable to generate a class.\n"); 563 error_sp->Flush(); 564 } 565 } 566 else 567 { 568 error_sp->Printf ("error: no script interpreter.\n"); 569 error_sp->Flush(); 570 } 571 } 572 else 573 { 574 error_sp->Printf ("error: internal synchronization data missing.\n"); 575 error_sp->Flush(); 576 } 577 } 578 else 579 { 580 error_sp->Printf ("error: empty function, didn't add python command.\n"); 581 error_sp->Flush(); 582 } 583 } 584 else 585 { 586 error_sp->Printf ("error: script interpreter missing, didn't add python command.\n"); 587 error_sp->Flush(); 588 } 589 590 #endif // LLDB_DISABLE_PYTHON 591 io_handler.SetIsDone(true); 592 } 593 594 public: 595 enum SynthFormatType 596 { 597 eRegularSynth, 598 eRegexSynth 599 }; 600 601 CommandObjectTypeSynthAdd (CommandInterpreter &interpreter); 602 603 ~CommandObjectTypeSynthAdd() override = default; 604 605 static bool 606 AddSynth(ConstString type_name, 607 lldb::SyntheticChildrenSP entry, 608 SynthFormatType type, 609 std::string category_name, 610 Error* error); 611 }; 612 613 //------------------------------------------------------------------------- 614 // CommandObjectTypeFormatAdd 615 //------------------------------------------------------------------------- 616 617 class CommandObjectTypeFormatAdd : public CommandObjectParsed 618 { 619 private: 620 class CommandOptions : public OptionGroup 621 { 622 public: 623 CommandOptions () : 624 OptionGroup() 625 { 626 } 627 628 ~CommandOptions() override = default; 629 630 uint32_t 631 GetNumDefinitions () override; 632 633 const OptionDefinition* 634 GetDefinitions () override 635 { 636 return g_option_table; 637 } 638 639 void 640 OptionParsingStarting (CommandInterpreter &interpreter) override 641 { 642 m_cascade = true; 643 m_skip_pointers = false; 644 m_skip_references = false; 645 m_regex = false; 646 m_category.assign("default"); 647 m_custom_type_name.clear(); 648 } 649 650 Error 651 SetOptionValue (CommandInterpreter &interpreter, 652 uint32_t option_idx, 653 const char *option_value) override 654 { 655 Error error; 656 const int short_option = g_option_table[option_idx].short_option; 657 bool success; 658 659 switch (short_option) 660 { 661 case 'C': 662 m_cascade = Args::StringToBoolean(option_value, true, &success); 663 if (!success) 664 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_value); 665 break; 666 case 'p': 667 m_skip_pointers = true; 668 break; 669 case 'w': 670 m_category.assign(option_value); 671 break; 672 case 'r': 673 m_skip_references = true; 674 break; 675 case 'x': 676 m_regex = true; 677 break; 678 case 't': 679 m_custom_type_name.assign(option_value); 680 break; 681 default: 682 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 683 break; 684 } 685 686 return error; 687 } 688 689 // Options table: Required for subclasses of Options. 690 691 static OptionDefinition g_option_table[]; 692 693 // Instance variables to hold the values for command options. 694 695 bool m_cascade; 696 bool m_skip_references; 697 bool m_skip_pointers; 698 bool m_regex; 699 std::string m_category; 700 std::string m_custom_type_name; 701 }; 702 703 OptionGroupOptions m_option_group; 704 OptionGroupFormat m_format_options; 705 CommandOptions m_command_options; 706 707 Options * 708 GetOptions () override 709 { 710 return &m_option_group; 711 } 712 713 public: 714 CommandObjectTypeFormatAdd (CommandInterpreter &interpreter) : 715 CommandObjectParsed(interpreter, 716 "type format add", 717 "Add a new formatting style for a type.", 718 nullptr), 719 m_option_group (interpreter), 720 m_format_options (eFormatInvalid), 721 m_command_options () 722 { 723 CommandArgumentEntry type_arg; 724 CommandArgumentData type_style_arg; 725 726 type_style_arg.arg_type = eArgTypeName; 727 type_style_arg.arg_repetition = eArgRepeatPlus; 728 729 type_arg.push_back (type_style_arg); 730 731 m_arguments.push_back (type_arg); 732 733 SetHelpLong( 734 R"( 735 The following examples of 'type format add' refer to this code snippet for context: 736 737 typedef int Aint; 738 typedef float Afloat; 739 typedef Aint Bint; 740 typedef Afloat Bfloat; 741 742 Aint ix = 5; 743 Bint iy = 5; 744 745 Afloat fx = 3.14; 746 BFloat fy = 3.14; 747 748 Adding default formatting: 749 750 (lldb) type format add -f hex AInt 751 (lldb) frame variable iy 752 753 )" " Produces hexidecimal display of iy, because no formatter is available for Bint and \ 754 the one for Aint is used instead." R"( 755 756 To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains: 757 758 759 (lldb) type format add -f hex -C no AInt 760 761 Similar reasoning applies to this: 762 763 (lldb) type format add -f hex -C no float -p 764 765 )" " All float values and float references are now formatted as hexadecimal, but not \ 766 pointers to floats. Nor will it change the default display for Afloat and Bfloat objects." 767 ); 768 769 // Add the "--format" to all options groups 770 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1); 771 m_option_group.Append (&m_command_options); 772 m_option_group.Finalize(); 773 } 774 775 ~CommandObjectTypeFormatAdd() override = default; 776 777 protected: 778 bool 779 DoExecute (Args& command, CommandReturnObject &result) override 780 { 781 const size_t argc = command.GetArgumentCount(); 782 783 if (argc < 1) 784 { 785 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 786 result.SetStatus(eReturnStatusFailed); 787 return false; 788 } 789 790 const Format format = m_format_options.GetFormat(); 791 if (format == eFormatInvalid && m_command_options.m_custom_type_name.empty()) 792 { 793 result.AppendErrorWithFormat ("%s needs a valid format.\n", m_cmd_name.c_str()); 794 result.SetStatus(eReturnStatusFailed); 795 return false; 796 } 797 798 TypeFormatImplSP entry; 799 800 if (m_command_options.m_custom_type_name.empty()) 801 entry.reset(new TypeFormatImpl_Format(format, 802 TypeFormatImpl::Flags().SetCascades(m_command_options.m_cascade). 803 SetSkipPointers(m_command_options.m_skip_pointers). 804 SetSkipReferences(m_command_options.m_skip_references))); 805 else 806 entry.reset(new TypeFormatImpl_EnumType(ConstString(m_command_options.m_custom_type_name.c_str()), 807 TypeFormatImpl::Flags().SetCascades(m_command_options.m_cascade). 808 SetSkipPointers(m_command_options.m_skip_pointers). 809 SetSkipReferences(m_command_options.m_skip_references))); 810 811 // now I have a valid format, let's add it to every type 812 813 TypeCategoryImplSP category_sp; 814 DataVisualization::Categories::GetCategory(ConstString(m_command_options.m_category), category_sp); 815 if (!category_sp) 816 return false; 817 818 WarnOnPotentialUnquotedUnsignedType(command, result); 819 820 for (size_t i = 0; i < argc; i++) 821 { 822 const char* typeA = command.GetArgumentAtIndex(i); 823 ConstString typeCS(typeA); 824 if (typeCS) 825 { 826 if (m_command_options.m_regex) 827 { 828 RegularExpressionSP typeRX(new RegularExpression()); 829 if (!typeRX->Compile(typeCS.GetCString())) 830 { 831 result.AppendError("regex format error (maybe this is not really a regex?)"); 832 result.SetStatus(eReturnStatusFailed); 833 return false; 834 } 835 category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS); 836 category_sp->GetRegexTypeFormatsContainer()->Add(typeRX, entry); 837 } 838 else 839 category_sp->GetTypeFormatsContainer()->Add(typeCS, entry); 840 } 841 else 842 { 843 result.AppendError("empty typenames not allowed"); 844 result.SetStatus(eReturnStatusFailed); 845 return false; 846 } 847 } 848 849 result.SetStatus(eReturnStatusSuccessFinishNoResult); 850 return result.Succeeded(); 851 } 852 }; 853 854 OptionDefinition 855 CommandObjectTypeFormatAdd::CommandOptions::g_option_table[] = 856 { 857 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 858 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, 859 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 860 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 861 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions."}, 862 { LLDB_OPT_SET_2, false, "type", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Format variables as if they were of this type."}, 863 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 864 }; 865 866 uint32_t 867 CommandObjectTypeFormatAdd::CommandOptions::GetNumDefinitions () 868 { 869 return sizeof(g_option_table) / sizeof (OptionDefinition); 870 } 871 872 class CommandObjectTypeFormatterDelete : public CommandObjectParsed 873 { 874 protected: 875 class CommandOptions : public Options 876 { 877 public: 878 CommandOptions (CommandInterpreter &interpreter) : 879 Options (interpreter) 880 { 881 } 882 883 ~CommandOptions() override = default; 884 885 Error 886 SetOptionValue (uint32_t option_idx, const char *option_arg) override 887 { 888 Error error; 889 const int short_option = m_getopt_table[option_idx].val; 890 891 switch (short_option) 892 { 893 case 'a': 894 m_delete_all = true; 895 break; 896 case 'w': 897 m_category = std::string(option_arg); 898 break; 899 case 'l': 900 m_language = Language::GetLanguageTypeFromString(option_arg); 901 break; 902 default: 903 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 904 break; 905 } 906 907 return error; 908 } 909 910 void 911 OptionParsingStarting () override 912 { 913 m_delete_all = false; 914 m_category = "default"; 915 m_language = lldb::eLanguageTypeUnknown; 916 } 917 918 const OptionDefinition* 919 GetDefinitions () override 920 { 921 return g_option_table; 922 } 923 924 // Options table: Required for subclasses of Options. 925 926 static OptionDefinition g_option_table[]; 927 928 // Instance variables to hold the values for command options. 929 930 bool m_delete_all; 931 std::string m_category; 932 lldb::LanguageType m_language; 933 }; 934 935 CommandOptions m_options; 936 uint32_t m_formatter_kind_mask; 937 938 Options * 939 GetOptions () override 940 { 941 return &m_options; 942 } 943 944 public: 945 CommandObjectTypeFormatterDelete (CommandInterpreter &interpreter, 946 uint32_t formatter_kind_mask, 947 const char* name, 948 const char* help) : 949 CommandObjectParsed(interpreter, 950 name, 951 help, 952 nullptr), 953 m_options(interpreter), 954 m_formatter_kind_mask(formatter_kind_mask) 955 { 956 CommandArgumentEntry type_arg; 957 CommandArgumentData type_style_arg; 958 959 type_style_arg.arg_type = eArgTypeName; 960 type_style_arg.arg_repetition = eArgRepeatPlain; 961 962 type_arg.push_back (type_style_arg); 963 964 m_arguments.push_back (type_arg); 965 } 966 967 ~CommandObjectTypeFormatterDelete() override = default; 968 969 protected: 970 virtual bool 971 FormatterSpecificDeletion (ConstString typeCS) 972 { 973 return false; 974 } 975 976 bool 977 DoExecute (Args& command, CommandReturnObject &result) override 978 { 979 const size_t argc = command.GetArgumentCount(); 980 981 if (argc != 1) 982 { 983 result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); 984 result.SetStatus(eReturnStatusFailed); 985 return false; 986 } 987 988 const char* typeA = command.GetArgumentAtIndex(0); 989 ConstString typeCS(typeA); 990 991 if (!typeCS) 992 { 993 result.AppendError("empty typenames not allowed"); 994 result.SetStatus(eReturnStatusFailed); 995 return false; 996 } 997 998 if (m_options.m_delete_all) 999 { 1000 DataVisualization::Categories::ForEach( [this, typeCS] (const lldb::TypeCategoryImplSP& category_sp) -> bool { 1001 category_sp->Delete(typeCS, m_formatter_kind_mask); 1002 return true; 1003 }); 1004 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1005 return result.Succeeded(); 1006 } 1007 1008 bool delete_category = false; 1009 bool extra_deletion = false; 1010 1011 if (m_options.m_language != lldb::eLanguageTypeUnknown) 1012 { 1013 lldb::TypeCategoryImplSP category; 1014 DataVisualization::Categories::GetCategory(m_options.m_language, category); 1015 if (category) 1016 delete_category = category->Delete(typeCS, m_formatter_kind_mask); 1017 extra_deletion = FormatterSpecificDeletion(typeCS); 1018 } 1019 else 1020 { 1021 lldb::TypeCategoryImplSP category; 1022 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 1023 if (category) 1024 delete_category = category->Delete(typeCS, m_formatter_kind_mask); 1025 extra_deletion = FormatterSpecificDeletion(typeCS); 1026 } 1027 1028 if (delete_category || extra_deletion) 1029 { 1030 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1031 return result.Succeeded(); 1032 } 1033 else 1034 { 1035 result.AppendErrorWithFormat ("no custom formatter for %s.\n", typeA); 1036 result.SetStatus(eReturnStatusFailed); 1037 return false; 1038 } 1039 } 1040 }; 1041 1042 OptionDefinition 1043 CommandObjectTypeFormatterDelete::CommandOptions::g_option_table[] = 1044 { 1045 { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete from every category."}, 1046 { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Delete from given category."}, 1047 { LLDB_OPT_SET_3, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Delete from given language's category."}, 1048 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 1049 }; 1050 1051 class CommandObjectTypeFormatterClear : public CommandObjectParsed 1052 { 1053 private: 1054 class CommandOptions : public Options 1055 { 1056 public: 1057 CommandOptions (CommandInterpreter &interpreter) : 1058 Options (interpreter) 1059 { 1060 } 1061 1062 ~CommandOptions() override = default; 1063 1064 Error 1065 SetOptionValue (uint32_t option_idx, const char *option_arg) override 1066 { 1067 Error error; 1068 const int short_option = m_getopt_table[option_idx].val; 1069 1070 switch (short_option) 1071 { 1072 case 'a': 1073 m_delete_all = true; 1074 break; 1075 default: 1076 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1077 break; 1078 } 1079 1080 return error; 1081 } 1082 1083 void 1084 OptionParsingStarting () override 1085 { 1086 m_delete_all = false; 1087 } 1088 1089 const OptionDefinition* 1090 GetDefinitions () override 1091 { 1092 return g_option_table; 1093 } 1094 1095 // Options table: Required for subclasses of Options. 1096 1097 static OptionDefinition g_option_table[]; 1098 1099 // Instance variables to hold the values for command options. 1100 bool m_delete_all; 1101 }; 1102 1103 CommandOptions m_options; 1104 uint32_t m_formatter_kind_mask; 1105 1106 Options * 1107 GetOptions () override 1108 { 1109 return &m_options; 1110 } 1111 1112 public: 1113 CommandObjectTypeFormatterClear (CommandInterpreter &interpreter, 1114 uint32_t formatter_kind_mask, 1115 const char* name, 1116 const char* help) : 1117 CommandObjectParsed(interpreter, 1118 name, 1119 help, 1120 nullptr), 1121 m_options(interpreter), 1122 m_formatter_kind_mask(formatter_kind_mask) 1123 { 1124 } 1125 1126 ~CommandObjectTypeFormatterClear() override = default; 1127 1128 protected: 1129 virtual void 1130 FormatterSpecificDeletion () 1131 { 1132 } 1133 1134 bool 1135 DoExecute (Args& command, CommandReturnObject &result) override 1136 { 1137 if (m_options.m_delete_all) 1138 { 1139 DataVisualization::Categories::ForEach( [this] (const TypeCategoryImplSP& category_sp) -> bool { 1140 category_sp->Clear(m_formatter_kind_mask); 1141 return true; 1142 }); 1143 } 1144 else 1145 { 1146 lldb::TypeCategoryImplSP category; 1147 if (command.GetArgumentCount() > 0) 1148 { 1149 const char* cat_name = command.GetArgumentAtIndex(0); 1150 ConstString cat_nameCS(cat_name); 1151 DataVisualization::Categories::GetCategory(cat_nameCS, category); 1152 } 1153 else 1154 { 1155 DataVisualization::Categories::GetCategory(ConstString(nullptr), category); 1156 } 1157 category->Clear(m_formatter_kind_mask); 1158 } 1159 1160 FormatterSpecificDeletion(); 1161 1162 result.SetStatus(eReturnStatusSuccessFinishResult); 1163 return result.Succeeded(); 1164 } 1165 }; 1166 1167 OptionDefinition 1168 CommandObjectTypeFormatterClear::CommandOptions::g_option_table[] = 1169 { 1170 { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Clear every category."}, 1171 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 1172 }; 1173 1174 //------------------------------------------------------------------------- 1175 // CommandObjectTypeFormatDelete 1176 //------------------------------------------------------------------------- 1177 1178 class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete 1179 { 1180 public: 1181 CommandObjectTypeFormatDelete (CommandInterpreter &interpreter) : 1182 CommandObjectTypeFormatterDelete (interpreter, 1183 eFormatCategoryItemValue | eFormatCategoryItemRegexValue, 1184 "type format delete", 1185 "Delete an existing formatting style for a type.") 1186 { 1187 } 1188 1189 ~CommandObjectTypeFormatDelete() override = default; 1190 }; 1191 1192 //------------------------------------------------------------------------- 1193 // CommandObjectTypeFormatClear 1194 //------------------------------------------------------------------------- 1195 1196 class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear 1197 { 1198 public: 1199 CommandObjectTypeFormatClear (CommandInterpreter &interpreter) : 1200 CommandObjectTypeFormatterClear (interpreter, 1201 eFormatCategoryItemValue | eFormatCategoryItemRegexValue, 1202 "type format clear", 1203 "Delete all existing format styles.") 1204 { 1205 } 1206 }; 1207 1208 template <typename FormatterType> 1209 class CommandObjectTypeFormatterList : public CommandObjectParsed 1210 { 1211 typedef typename FormatterType::SharedPointer FormatterSharedPointer; 1212 1213 class CommandOptions : public Options 1214 { 1215 public: 1216 CommandOptions (CommandInterpreter &interpreter) : 1217 Options (interpreter), 1218 m_category_regex("",""), 1219 m_category_language(lldb::eLanguageTypeUnknown, lldb::eLanguageTypeUnknown) 1220 { 1221 } 1222 1223 ~CommandOptions() override = default; 1224 1225 Error 1226 SetOptionValue (uint32_t option_idx, const char *option_arg) override 1227 { 1228 Error error; 1229 const int short_option = m_getopt_table[option_idx].val; 1230 1231 switch (short_option) 1232 { 1233 case 'w': 1234 m_category_regex.SetCurrentValue(option_arg); 1235 m_category_regex.SetOptionWasSet(); 1236 break; 1237 case 'l': 1238 error = m_category_language.SetValueFromString(option_arg); 1239 if (error.Success()) 1240 m_category_language.SetOptionWasSet(); 1241 break; 1242 default: 1243 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1244 break; 1245 } 1246 1247 return error; 1248 } 1249 1250 void 1251 OptionParsingStarting () override 1252 { 1253 m_category_regex.Clear(); 1254 m_category_language.Clear(); 1255 } 1256 1257 const OptionDefinition* 1258 GetDefinitions () override 1259 { 1260 static OptionDefinition g_option_table[] = 1261 { 1262 { LLDB_OPT_SET_1, false, "category-regex", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Only show categories matching this filter."}, 1263 { LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Only show the category for a specific language."}, 1264 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 1265 }; 1266 1267 return g_option_table; 1268 } 1269 1270 // Options table: Required for subclasses of Options. 1271 1272 static OptionDefinition g_option_table[]; 1273 1274 // Instance variables to hold the values for command options. 1275 1276 OptionValueString m_category_regex; 1277 OptionValueLanguage m_category_language; 1278 }; 1279 1280 CommandOptions m_options; 1281 1282 Options * 1283 GetOptions () override 1284 { 1285 return &m_options; 1286 } 1287 1288 public: 1289 CommandObjectTypeFormatterList (CommandInterpreter &interpreter, 1290 const char* name, 1291 const char* help) : 1292 CommandObjectParsed(interpreter, 1293 name, 1294 help, 1295 nullptr), 1296 m_options(interpreter) 1297 { 1298 CommandArgumentEntry type_arg; 1299 CommandArgumentData type_style_arg; 1300 1301 type_style_arg.arg_type = eArgTypeName; 1302 type_style_arg.arg_repetition = eArgRepeatOptional; 1303 1304 type_arg.push_back (type_style_arg); 1305 1306 m_arguments.push_back (type_arg); 1307 } 1308 1309 ~CommandObjectTypeFormatterList() override = default; 1310 1311 protected: 1312 virtual void 1313 FormatterSpecificList (CommandReturnObject &result) 1314 { 1315 } 1316 1317 bool 1318 DoExecute (Args& command, CommandReturnObject &result) override 1319 { 1320 const size_t argc = command.GetArgumentCount(); 1321 1322 std::unique_ptr<RegularExpression> category_regex; 1323 std::unique_ptr<RegularExpression> formatter_regex; 1324 1325 if (m_options.m_category_regex.OptionWasSet()) 1326 { 1327 category_regex.reset(new RegularExpression()); 1328 if (!category_regex->Compile(m_options.m_category_regex.GetCurrentValue())) 1329 { 1330 result.AppendErrorWithFormat("syntax error in category regular expression '%s'", m_options.m_category_regex.GetCurrentValue()); 1331 result.SetStatus(eReturnStatusFailed); 1332 return false; 1333 } 1334 } 1335 1336 if (argc == 1) 1337 { 1338 const char* arg = command.GetArgumentAtIndex(0); 1339 formatter_regex.reset(new RegularExpression()); 1340 if (!formatter_regex->Compile(arg)) 1341 { 1342 result.AppendErrorWithFormat("syntax error in regular expression '%s'", arg); 1343 result.SetStatus(eReturnStatusFailed); 1344 return false; 1345 } 1346 } 1347 1348 auto category_closure = [&result, &formatter_regex] (const lldb::TypeCategoryImplSP& category) -> void { 1349 result.GetOutputStream().Printf("-----------------------\nCategory: %s\n-----------------------\n", category->GetName()); 1350 TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach; 1351 foreach.SetExact([&result, &formatter_regex] (ConstString name, const FormatterSharedPointer& format_sp) -> bool { 1352 if (formatter_regex) 1353 { 1354 bool escape = true; 1355 if (0 == strcmp(name.AsCString(), formatter_regex->GetText())) 1356 { 1357 escape = false; 1358 } 1359 else if (formatter_regex->Execute(name.AsCString())) 1360 { 1361 escape = false; 1362 } 1363 1364 if (escape) 1365 return true; 1366 } 1367 1368 result.GetOutputStream().Printf ("%s: %s\n", name.AsCString(), format_sp->GetDescription().c_str()); 1369 1370 return true; 1371 }); 1372 1373 foreach.SetWithRegex( [&result, &formatter_regex] (RegularExpressionSP regex_sp, const FormatterSharedPointer& format_sp) -> bool { 1374 if (formatter_regex) 1375 { 1376 bool escape = true; 1377 if (0 == strcmp(regex_sp->GetText(), formatter_regex->GetText())) 1378 { 1379 escape = false; 1380 } 1381 else if (formatter_regex->Execute(regex_sp->GetText())) 1382 { 1383 escape = false; 1384 } 1385 1386 if (escape) 1387 return true; 1388 } 1389 1390 result.GetOutputStream().Printf ("%s: %s\n", regex_sp->GetText(), format_sp->GetDescription().c_str()); 1391 1392 return true; 1393 }); 1394 1395 category->ForEach(foreach); 1396 }; 1397 1398 if (m_options.m_category_language.OptionWasSet()) 1399 { 1400 lldb::TypeCategoryImplSP category_sp; 1401 DataVisualization::Categories::GetCategory(m_options.m_category_language.GetCurrentValue(), category_sp); 1402 if (category_sp) 1403 category_closure(category_sp); 1404 } 1405 else 1406 { 1407 DataVisualization::Categories::ForEach( [this, &command, &result, &category_regex, &formatter_regex, &category_closure] (const lldb::TypeCategoryImplSP& category) -> bool { 1408 if (category_regex) 1409 { 1410 bool escape = true; 1411 if (0 == strcmp(category->GetName(), category_regex->GetText())) 1412 { 1413 escape = false; 1414 } 1415 else if (category_regex->Execute(category->GetName())) 1416 { 1417 escape = false; 1418 } 1419 1420 if (escape) 1421 return true; 1422 } 1423 1424 category_closure(category); 1425 1426 return true; 1427 }); 1428 1429 FormatterSpecificList(result); 1430 } 1431 1432 result.SetStatus(eReturnStatusSuccessFinishResult); 1433 return result.Succeeded(); 1434 } 1435 }; 1436 1437 //------------------------------------------------------------------------- 1438 // CommandObjectTypeFormatList 1439 //------------------------------------------------------------------------- 1440 1441 class CommandObjectTypeFormatList : public CommandObjectTypeFormatterList<TypeFormatImpl> 1442 { 1443 public: 1444 1445 CommandObjectTypeFormatList (CommandInterpreter &interpreter) : 1446 CommandObjectTypeFormatterList(interpreter, 1447 "type format list", 1448 "Show a list of current formats.") 1449 { 1450 } 1451 }; 1452 1453 #ifndef LLDB_DISABLE_PYTHON 1454 1455 //------------------------------------------------------------------------- 1456 // CommandObjectTypeSummaryAdd 1457 //------------------------------------------------------------------------- 1458 1459 #endif // LLDB_DISABLE_PYTHON 1460 1461 Error 1462 CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) 1463 { 1464 Error error; 1465 const int short_option = m_getopt_table[option_idx].val; 1466 bool success; 1467 1468 switch (short_option) 1469 { 1470 case 'C': 1471 m_flags.SetCascades(Args::StringToBoolean(option_arg, true, &success)); 1472 if (!success) 1473 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg); 1474 break; 1475 case 'e': 1476 m_flags.SetDontShowChildren(false); 1477 break; 1478 case 'h': 1479 m_flags.SetHideEmptyAggregates(true); 1480 break; 1481 case 'v': 1482 m_flags.SetDontShowValue(true); 1483 break; 1484 case 'c': 1485 m_flags.SetShowMembersOneLiner(true); 1486 break; 1487 case 's': 1488 m_format_string = std::string(option_arg); 1489 break; 1490 case 'p': 1491 m_flags.SetSkipPointers(true); 1492 break; 1493 case 'r': 1494 m_flags.SetSkipReferences(true); 1495 break; 1496 case 'x': 1497 m_regex = true; 1498 break; 1499 case 'n': 1500 m_name.SetCString(option_arg); 1501 break; 1502 case 'o': 1503 m_python_script = std::string(option_arg); 1504 m_is_add_script = true; 1505 break; 1506 case 'F': 1507 m_python_function = std::string(option_arg); 1508 m_is_add_script = true; 1509 break; 1510 case 'P': 1511 m_is_add_script = true; 1512 break; 1513 case 'w': 1514 m_category = std::string(option_arg); 1515 break; 1516 case 'O': 1517 m_flags.SetHideItemNames(true); 1518 break; 1519 default: 1520 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1521 break; 1522 } 1523 1524 return error; 1525 } 1526 1527 void 1528 CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting () 1529 { 1530 m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false); 1531 m_flags.SetShowMembersOneLiner(false).SetSkipPointers(false).SetSkipReferences(false).SetHideItemNames(false); 1532 1533 m_regex = false; 1534 m_name.Clear(); 1535 m_python_script = ""; 1536 m_python_function = ""; 1537 m_format_string = ""; 1538 m_is_add_script = false; 1539 m_category = "default"; 1540 } 1541 1542 #ifndef LLDB_DISABLE_PYTHON 1543 1544 bool 1545 CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturnObject &result) 1546 { 1547 const size_t argc = command.GetArgumentCount(); 1548 1549 if (argc < 1 && !m_options.m_name) 1550 { 1551 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 1552 result.SetStatus(eReturnStatusFailed); 1553 return false; 1554 } 1555 1556 TypeSummaryImplSP script_format; 1557 1558 if (!m_options.m_python_function.empty()) // we have a Python function ready to use 1559 { 1560 const char *funct_name = m_options.m_python_function.c_str(); 1561 if (!funct_name || !funct_name[0]) 1562 { 1563 result.AppendError ("function name empty.\n"); 1564 result.SetStatus (eReturnStatusFailed); 1565 return false; 1566 } 1567 1568 std::string code = (" " + m_options.m_python_function + "(valobj,internal_dict)"); 1569 1570 script_format.reset(new ScriptSummaryFormat(m_options.m_flags, 1571 funct_name, 1572 code.c_str())); 1573 1574 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 1575 1576 if (interpreter && !interpreter->CheckObjectExists(funct_name)) 1577 result.AppendWarningWithFormat("The provided function \"%s\" does not exist - " 1578 "please define it before attempting to use this summary.\n", 1579 funct_name); 1580 } 1581 else if (!m_options.m_python_script.empty()) // we have a quick 1-line script, just use it 1582 { 1583 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 1584 if (!interpreter) 1585 { 1586 result.AppendError ("script interpreter missing - unable to generate function wrapper.\n"); 1587 result.SetStatus (eReturnStatusFailed); 1588 return false; 1589 } 1590 StringList funct_sl; 1591 funct_sl << m_options.m_python_script.c_str(); 1592 std::string funct_name_str; 1593 if (!interpreter->GenerateTypeScriptFunction (funct_sl, 1594 funct_name_str)) 1595 { 1596 result.AppendError ("unable to generate function wrapper.\n"); 1597 result.SetStatus (eReturnStatusFailed); 1598 return false; 1599 } 1600 if (funct_name_str.empty()) 1601 { 1602 result.AppendError ("script interpreter failed to generate a valid function name.\n"); 1603 result.SetStatus (eReturnStatusFailed); 1604 return false; 1605 } 1606 1607 std::string code = " " + m_options.m_python_script; 1608 1609 script_format.reset(new ScriptSummaryFormat(m_options.m_flags, 1610 funct_name_str.c_str(), 1611 code.c_str())); 1612 } 1613 else 1614 { 1615 // Use an IOHandler to grab Python code from the user 1616 ScriptAddOptions *options = new ScriptAddOptions(m_options.m_flags, 1617 m_options.m_regex, 1618 m_options.m_name, 1619 m_options.m_category); 1620 1621 for (size_t i = 0; i < argc; i++) 1622 { 1623 const char* typeA = command.GetArgumentAtIndex(i); 1624 if (typeA && *typeA) 1625 options->m_target_types << typeA; 1626 else 1627 { 1628 result.AppendError("empty typenames not allowed"); 1629 result.SetStatus(eReturnStatusFailed); 1630 return false; 1631 } 1632 } 1633 1634 m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt 1635 *this, // IOHandlerDelegate 1636 true, // Run IOHandler in async mode 1637 options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions 1638 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1639 1640 return result.Succeeded(); 1641 } 1642 1643 // if I am here, script_format must point to something good, so I can add that 1644 // as a script summary to all interested parties 1645 1646 Error error; 1647 1648 for (size_t i = 0; i < command.GetArgumentCount(); i++) 1649 { 1650 const char *type_name = command.GetArgumentAtIndex(i); 1651 CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name), 1652 script_format, 1653 (m_options.m_regex ? eRegexSummary : eRegularSummary), 1654 m_options.m_category, 1655 &error); 1656 if (error.Fail()) 1657 { 1658 result.AppendError(error.AsCString()); 1659 result.SetStatus(eReturnStatusFailed); 1660 return false; 1661 } 1662 } 1663 1664 if (m_options.m_name) 1665 { 1666 AddSummary(m_options.m_name, script_format, eNamedSummary, m_options.m_category, &error); 1667 if (error.Fail()) 1668 { 1669 result.AppendError(error.AsCString()); 1670 result.AppendError("added to types, but not given a name"); 1671 result.SetStatus(eReturnStatusFailed); 1672 return false; 1673 } 1674 } 1675 1676 return result.Succeeded(); 1677 } 1678 1679 #endif // LLDB_DISABLE_PYTHON 1680 1681 bool 1682 CommandObjectTypeSummaryAdd::Execute_StringSummary (Args& command, CommandReturnObject &result) 1683 { 1684 const size_t argc = command.GetArgumentCount(); 1685 1686 if (argc < 1 && !m_options.m_name) 1687 { 1688 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 1689 result.SetStatus(eReturnStatusFailed); 1690 return false; 1691 } 1692 1693 if (!m_options.m_flags.GetShowMembersOneLiner() && m_options.m_format_string.empty()) 1694 { 1695 result.AppendError("empty summary strings not allowed"); 1696 result.SetStatus(eReturnStatusFailed); 1697 return false; 1698 } 1699 1700 const char* format_cstr = (m_options.m_flags.GetShowMembersOneLiner() ? "" : m_options.m_format_string.c_str()); 1701 1702 // ${var%S} is an endless recursion, prevent it 1703 if (strcmp(format_cstr, "${var%S}") == 0) 1704 { 1705 result.AppendError("recursive summary not allowed"); 1706 result.SetStatus(eReturnStatusFailed); 1707 return false; 1708 } 1709 1710 Error error; 1711 1712 lldb::TypeSummaryImplSP entry(new StringSummaryFormat(m_options.m_flags, 1713 format_cstr)); 1714 1715 if (error.Fail()) 1716 { 1717 result.AppendError(error.AsCString()); 1718 result.SetStatus(eReturnStatusFailed); 1719 return false; 1720 } 1721 1722 // now I have a valid format, let's add it to every type 1723 1724 for (size_t i = 0; i < argc; i++) 1725 { 1726 const char* typeA = command.GetArgumentAtIndex(i); 1727 if (!typeA || typeA[0] == '\0') 1728 { 1729 result.AppendError("empty typenames not allowed"); 1730 result.SetStatus(eReturnStatusFailed); 1731 return false; 1732 } 1733 ConstString typeCS(typeA); 1734 1735 AddSummary(typeCS, 1736 entry, 1737 (m_options.m_regex ? eRegexSummary : eRegularSummary), 1738 m_options.m_category, 1739 &error); 1740 1741 if (error.Fail()) 1742 { 1743 result.AppendError(error.AsCString()); 1744 result.SetStatus(eReturnStatusFailed); 1745 return false; 1746 } 1747 } 1748 1749 if (m_options.m_name) 1750 { 1751 AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category, &error); 1752 if (error.Fail()) 1753 { 1754 result.AppendError(error.AsCString()); 1755 result.AppendError("added to types, but not given a name"); 1756 result.SetStatus(eReturnStatusFailed); 1757 return false; 1758 } 1759 } 1760 1761 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1762 return result.Succeeded(); 1763 } 1764 1765 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter) : 1766 CommandObjectParsed(interpreter, 1767 "type summary add", 1768 "Add a new summary style for a type.", 1769 nullptr), 1770 IOHandlerDelegateMultiline ("DONE"), 1771 m_options (interpreter) 1772 { 1773 CommandArgumentEntry type_arg; 1774 CommandArgumentData type_style_arg; 1775 1776 type_style_arg.arg_type = eArgTypeName; 1777 type_style_arg.arg_repetition = eArgRepeatPlus; 1778 1779 type_arg.push_back (type_style_arg); 1780 1781 m_arguments.push_back (type_arg); 1782 1783 SetHelpLong( 1784 R"( 1785 The following examples of 'type summary add' refer to this code snippet for context: 1786 1787 struct JustADemo 1788 { 1789 int* ptr; 1790 float value; 1791 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {} 1792 }; 1793 JustADemo demo_instance(42, 3.14); 1794 1795 typedef JustADemo NewDemo; 1796 NewDemo new_demo_instance(42, 3.14); 1797 1798 (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo 1799 1800 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42" 1801 1802 (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo 1803 1804 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14" 1805 1806 )" "Alternatively, you could define formatting for all pointers to integers and \ 1807 rely on that when formatting JustADemo to obtain the same result:" R"( 1808 1809 (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *" 1810 (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo 1811 1812 )" "Type summaries are automatically applied to derived typedefs, so the examples \ 1813 above apply to both JustADemo and NewDemo. The cascade option can be used to \ 1814 suppress this behavior:" R"( 1815 1816 (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no 1817 1818 The summary will now be used for values of JustADemo but not NewDemo. 1819 1820 )" "By default summaries are shown for pointers and references to values of the \ 1821 specified type. To suppress formatting for pointers use the -p option, or apply \ 1822 the corresponding -r option to suppress formatting for references:" R"( 1823 1824 (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo 1825 1826 )" "One-line summaries including all fields in a type can be inferred without supplying an \ 1827 explicit summary string by passing the -c option:" R"( 1828 1829 (lldb) type summary add -c JustADemo 1830 (lldb) frame variable demo_instance 1831 (ptr=<address>, value=3.14) 1832 1833 )" "Type summaries normally suppress the nested display of individual fields. To \ 1834 supply a summary to supplement the default structure add the -e option:" R"( 1835 1836 (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo 1837 1838 )" "Now when displaying JustADemo values the int* is displayed, followed by the \ 1839 standard LLDB sequence of children, one per line:" R"( 1840 1841 *ptr = 42 { 1842 ptr = <address> 1843 value = 3.14 1844 } 1845 1846 )" "You can also add summaries written in Python. These scripts use lldb public API to \ 1847 gather information from your variables and produce a meaningful summary. To start a \ 1848 multi-line script use the -P option. The function declaration will be displayed along with \ 1849 a comment describing the two arguments. End your script with the word 'DONE' on a line by \ 1850 itself:" R"( 1851 1852 (lldb) type summary add JustADemo -P 1853 def function (valobj,internal_dict): 1854 """valobj: an SBValue which you want to provide a summary for 1855 internal_dict: an LLDB support object not to be used""" 1856 value = valobj.GetChildMemberWithName('value'); 1857 return 'My value is ' + value.GetValue(); 1858 DONE 1859 1860 Alternatively, the -o option can be used when providing a simple one-line Python script: 1861 1862 (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")" 1863 ); 1864 } 1865 1866 bool 1867 CommandObjectTypeSummaryAdd::DoExecute (Args& command, CommandReturnObject &result) 1868 { 1869 WarnOnPotentialUnquotedUnsignedType(command, result); 1870 1871 if (m_options.m_is_add_script) 1872 { 1873 #ifndef LLDB_DISABLE_PYTHON 1874 return Execute_ScriptSummary(command, result); 1875 #else 1876 result.AppendError ("python is disabled"); 1877 result.SetStatus(eReturnStatusFailed); 1878 return false; 1879 #endif // LLDB_DISABLE_PYTHON 1880 } 1881 1882 return Execute_StringSummary(command, result); 1883 } 1884 1885 static bool 1886 FixArrayTypeNameWithRegex (ConstString &type_name) 1887 { 1888 llvm::StringRef type_name_ref(type_name.GetStringRef()); 1889 1890 if (type_name_ref.endswith("[]")) 1891 { 1892 std::string type_name_str(type_name.GetCString()); 1893 type_name_str.resize(type_name_str.length()-2); 1894 if (type_name_str.back() != ' ') 1895 type_name_str.append(" \\[[0-9]+\\]"); 1896 else 1897 type_name_str.append("\\[[0-9]+\\]"); 1898 type_name.SetCString(type_name_str.c_str()); 1899 return true; 1900 } 1901 return false; 1902 } 1903 1904 bool 1905 CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, 1906 TypeSummaryImplSP entry, 1907 SummaryFormatType type, 1908 std::string category_name, 1909 Error* error) 1910 { 1911 lldb::TypeCategoryImplSP category; 1912 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); 1913 1914 if (type == eRegularSummary) 1915 { 1916 if (FixArrayTypeNameWithRegex (type_name)) 1917 type = eRegexSummary; 1918 } 1919 1920 if (type == eRegexSummary) 1921 { 1922 RegularExpressionSP typeRX(new RegularExpression()); 1923 if (!typeRX->Compile(type_name.GetCString())) 1924 { 1925 if (error) 1926 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 1927 return false; 1928 } 1929 1930 category->GetRegexTypeSummariesContainer()->Delete(type_name); 1931 category->GetRegexTypeSummariesContainer()->Add(typeRX, entry); 1932 1933 return true; 1934 } 1935 else if (type == eNamedSummary) 1936 { 1937 // system named summaries do not exist (yet?) 1938 DataVisualization::NamedSummaryFormats::Add(type_name,entry); 1939 return true; 1940 } 1941 else 1942 { 1943 category->GetTypeSummariesContainer()->Add(type_name, entry); 1944 return true; 1945 } 1946 } 1947 1948 OptionDefinition 1949 CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = 1950 { 1951 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 1952 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, 1953 { LLDB_OPT_SET_ALL, false, "no-value", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't show the value, just show the summary, for this type."}, 1954 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 1955 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 1956 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions."}, 1957 { LLDB_OPT_SET_1 , true, "inline-children", 'c', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If true, inline all child values into summary string."}, 1958 { LLDB_OPT_SET_1 , false, "omit-names", 'O', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If true, omit value names in the summary display."}, 1959 { LLDB_OPT_SET_2 , true, "summary-string", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeSummaryString, "Summary string used to display text and object contents."}, 1960 { LLDB_OPT_SET_3, false, "python-script", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonScript, "Give a one-liner Python script as part of the command."}, 1961 { LLDB_OPT_SET_3, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Give the name of a Python function to use for this type."}, 1962 { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Input Python code to use for this type manually."}, 1963 { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Expand aggregate data types to show children on separate lines."}, 1964 { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "hide-empty", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Do not expand aggregate data types with no children."}, 1965 { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "A name for this summary string."}, 1966 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 1967 }; 1968 1969 //------------------------------------------------------------------------- 1970 // CommandObjectTypeSummaryDelete 1971 //------------------------------------------------------------------------- 1972 1973 class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete 1974 { 1975 public: 1976 CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) : 1977 CommandObjectTypeFormatterDelete (interpreter, 1978 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, 1979 "type summary delete", 1980 "Delete an existing summary for a type.") 1981 { 1982 } 1983 1984 ~CommandObjectTypeSummaryDelete() override = default; 1985 1986 protected: 1987 bool 1988 FormatterSpecificDeletion (ConstString typeCS) override 1989 { 1990 if (m_options.m_language != lldb::eLanguageTypeUnknown) 1991 return false; 1992 return DataVisualization::NamedSummaryFormats::Delete(typeCS); 1993 } 1994 }; 1995 1996 class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear 1997 { 1998 public: 1999 CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) : 2000 CommandObjectTypeFormatterClear (interpreter, 2001 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, 2002 "type summary clear", 2003 "Delete all existing summaries.") 2004 { 2005 } 2006 2007 protected: 2008 void 2009 FormatterSpecificDeletion () override 2010 { 2011 DataVisualization::NamedSummaryFormats::Clear(); 2012 } 2013 }; 2014 2015 //------------------------------------------------------------------------- 2016 // CommandObjectTypeSummaryList 2017 //------------------------------------------------------------------------- 2018 2019 class CommandObjectTypeSummaryList : public CommandObjectTypeFormatterList<TypeSummaryImpl> 2020 { 2021 public: 2022 CommandObjectTypeSummaryList (CommandInterpreter &interpreter) : 2023 CommandObjectTypeFormatterList(interpreter, 2024 "type summary list", 2025 "Show a list of current summaries.") 2026 { 2027 } 2028 2029 protected: 2030 void 2031 FormatterSpecificList (CommandReturnObject &result) override 2032 { 2033 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) 2034 { 2035 result.GetOutputStream().Printf("Named summaries:\n"); 2036 DataVisualization::NamedSummaryFormats::ForEach( [&result] (ConstString name, const TypeSummaryImplSP& summary_sp) -> bool { 2037 result.GetOutputStream().Printf ("%s: %s\n", name.AsCString(), summary_sp->GetDescription().c_str()); 2038 return true; 2039 }); 2040 } 2041 } 2042 }; 2043 2044 //------------------------------------------------------------------------- 2045 // CommandObjectTypeCategoryDefine 2046 //------------------------------------------------------------------------- 2047 2048 class CommandObjectTypeCategoryDefine : public CommandObjectParsed 2049 { 2050 class CommandOptions : public Options 2051 { 2052 public: 2053 CommandOptions (CommandInterpreter &interpreter) : 2054 Options (interpreter), 2055 m_define_enabled(false,false), 2056 m_cate_language(eLanguageTypeUnknown,eLanguageTypeUnknown) 2057 { 2058 } 2059 2060 ~CommandOptions() override = default; 2061 2062 Error 2063 SetOptionValue (uint32_t option_idx, const char *option_arg) override 2064 { 2065 Error error; 2066 const int short_option = m_getopt_table[option_idx].val; 2067 2068 switch (short_option) 2069 { 2070 case 'e': 2071 m_define_enabled.SetValueFromString("true"); 2072 break; 2073 case 'l': 2074 error = m_cate_language.SetValueFromString(option_arg); 2075 break; 2076 default: 2077 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2078 break; 2079 } 2080 2081 return error; 2082 } 2083 2084 void 2085 OptionParsingStarting () override 2086 { 2087 m_define_enabled.Clear(); 2088 m_cate_language.Clear(); 2089 } 2090 2091 const OptionDefinition* 2092 GetDefinitions () override 2093 { 2094 return g_option_table; 2095 } 2096 2097 // Options table: Required for subclasses of Options. 2098 2099 static OptionDefinition g_option_table[]; 2100 2101 // Instance variables to hold the values for command options. 2102 2103 OptionValueBoolean m_define_enabled; 2104 OptionValueLanguage m_cate_language; 2105 }; 2106 2107 CommandOptions m_options; 2108 2109 Options * 2110 GetOptions () override 2111 { 2112 return &m_options; 2113 } 2114 2115 public: 2116 CommandObjectTypeCategoryDefine (CommandInterpreter &interpreter) : 2117 CommandObjectParsed(interpreter, 2118 "type category define", 2119 "Define a new category as a source of formatters.", 2120 nullptr), 2121 m_options(interpreter) 2122 { 2123 CommandArgumentEntry type_arg; 2124 CommandArgumentData type_style_arg; 2125 2126 type_style_arg.arg_type = eArgTypeName; 2127 type_style_arg.arg_repetition = eArgRepeatPlus; 2128 2129 type_arg.push_back (type_style_arg); 2130 2131 m_arguments.push_back (type_arg); 2132 } 2133 2134 ~CommandObjectTypeCategoryDefine() override = default; 2135 2136 protected: 2137 bool 2138 DoExecute (Args& command, CommandReturnObject &result) override 2139 { 2140 const size_t argc = command.GetArgumentCount(); 2141 2142 if (argc < 1) 2143 { 2144 result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str()); 2145 result.SetStatus(eReturnStatusFailed); 2146 return false; 2147 } 2148 2149 for (size_t i = 0; i < argc; i++) 2150 { 2151 const char* cateName = command.GetArgumentAtIndex(i); 2152 TypeCategoryImplSP category_sp; 2153 if (DataVisualization::Categories::GetCategory(ConstString(cateName), category_sp) && category_sp) 2154 { 2155 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue()); 2156 if (m_options.m_define_enabled.GetCurrentValue()) 2157 DataVisualization::Categories::Enable(category_sp, TypeCategoryMap::Default); 2158 } 2159 } 2160 2161 result.SetStatus(eReturnStatusSuccessFinishResult); 2162 return result.Succeeded(); 2163 } 2164 }; 2165 2166 OptionDefinition 2167 CommandObjectTypeCategoryDefine::CommandOptions::g_option_table[] = 2168 { 2169 { LLDB_OPT_SET_ALL, false, "enabled", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If specified, this category will be created enabled."}, 2170 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specify the language that this category is supported for."}, 2171 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 2172 }; 2173 2174 //------------------------------------------------------------------------- 2175 // CommandObjectTypeCategoryEnable 2176 //------------------------------------------------------------------------- 2177 2178 class CommandObjectTypeCategoryEnable : public CommandObjectParsed 2179 { 2180 class CommandOptions : public Options 2181 { 2182 public: 2183 CommandOptions (CommandInterpreter &interpreter) : 2184 Options (interpreter) 2185 { 2186 } 2187 2188 ~CommandOptions() override = default; 2189 2190 Error 2191 SetOptionValue (uint32_t option_idx, const char *option_arg) override 2192 { 2193 Error error; 2194 const int short_option = m_getopt_table[option_idx].val; 2195 2196 switch (short_option) 2197 { 2198 case 'l': 2199 if (option_arg) 2200 { 2201 m_language = Language::GetLanguageTypeFromString(option_arg); 2202 if (m_language == lldb::eLanguageTypeUnknown) 2203 error.SetErrorStringWithFormat ("unrecognized language '%s'", option_arg); 2204 } 2205 break; 2206 default: 2207 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2208 break; 2209 } 2210 2211 return error; 2212 } 2213 2214 void 2215 OptionParsingStarting () override 2216 { 2217 m_language = lldb::eLanguageTypeUnknown; 2218 } 2219 2220 const OptionDefinition* 2221 GetDefinitions () override 2222 { 2223 return g_option_table; 2224 } 2225 2226 // Options table: Required for subclasses of Options. 2227 2228 static OptionDefinition g_option_table[]; 2229 2230 // Instance variables to hold the values for command options. 2231 2232 lldb::LanguageType m_language; 2233 2234 }; 2235 2236 CommandOptions m_options; 2237 2238 Options * 2239 GetOptions () override 2240 { 2241 return &m_options; 2242 } 2243 2244 public: 2245 CommandObjectTypeCategoryEnable (CommandInterpreter &interpreter) : 2246 CommandObjectParsed(interpreter, 2247 "type category enable", 2248 "Enable a category as a source of formatters.", 2249 nullptr), 2250 m_options(interpreter) 2251 { 2252 CommandArgumentEntry type_arg; 2253 CommandArgumentData type_style_arg; 2254 2255 type_style_arg.arg_type = eArgTypeName; 2256 type_style_arg.arg_repetition = eArgRepeatPlus; 2257 2258 type_arg.push_back (type_style_arg); 2259 2260 m_arguments.push_back (type_arg); 2261 2262 } 2263 2264 ~CommandObjectTypeCategoryEnable() override = default; 2265 2266 protected: 2267 bool 2268 DoExecute (Args& command, CommandReturnObject &result) override 2269 { 2270 const size_t argc = command.GetArgumentCount(); 2271 2272 if (argc < 1 && 2273 m_options.m_language == lldb::eLanguageTypeUnknown) 2274 { 2275 result.AppendErrorWithFormat ("%s takes arguments and/or a language", m_cmd_name.c_str()); 2276 result.SetStatus(eReturnStatusFailed); 2277 return false; 2278 } 2279 2280 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0) 2281 { 2282 DataVisualization::Categories::EnableStar(); 2283 } 2284 else if (argc > 0) 2285 { 2286 for (int i = argc - 1; i >= 0; i--) 2287 { 2288 const char* typeA = command.GetArgumentAtIndex(i); 2289 ConstString typeCS(typeA); 2290 2291 if (!typeCS) 2292 { 2293 result.AppendError("empty category name not allowed"); 2294 result.SetStatus(eReturnStatusFailed); 2295 return false; 2296 } 2297 DataVisualization::Categories::Enable(typeCS); 2298 lldb::TypeCategoryImplSP cate; 2299 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) 2300 { 2301 if (cate->GetCount() == 0) 2302 { 2303 result.AppendWarning("empty category enabled (typo?)"); 2304 } 2305 } 2306 } 2307 } 2308 2309 if (m_options.m_language != lldb::eLanguageTypeUnknown) 2310 DataVisualization::Categories::Enable(m_options.m_language); 2311 2312 result.SetStatus(eReturnStatusSuccessFinishResult); 2313 return result.Succeeded(); 2314 } 2315 }; 2316 2317 OptionDefinition 2318 CommandObjectTypeCategoryEnable::CommandOptions::g_option_table[] = 2319 { 2320 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Enable the category for this language."}, 2321 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 2322 }; 2323 2324 //------------------------------------------------------------------------- 2325 // CommandObjectTypeCategoryDelete 2326 //------------------------------------------------------------------------- 2327 2328 class CommandObjectTypeCategoryDelete : public CommandObjectParsed 2329 { 2330 public: 2331 CommandObjectTypeCategoryDelete (CommandInterpreter &interpreter) : 2332 CommandObjectParsed(interpreter, 2333 "type category delete", 2334 "Delete a category and all associated formatters.", 2335 nullptr) 2336 { 2337 CommandArgumentEntry type_arg; 2338 CommandArgumentData type_style_arg; 2339 2340 type_style_arg.arg_type = eArgTypeName; 2341 type_style_arg.arg_repetition = eArgRepeatPlus; 2342 2343 type_arg.push_back (type_style_arg); 2344 2345 m_arguments.push_back (type_arg); 2346 } 2347 2348 ~CommandObjectTypeCategoryDelete() override = default; 2349 2350 protected: 2351 bool 2352 DoExecute (Args& command, CommandReturnObject &result) override 2353 { 2354 const size_t argc = command.GetArgumentCount(); 2355 2356 if (argc < 1) 2357 { 2358 result.AppendErrorWithFormat ("%s takes 1 or more arg.\n", m_cmd_name.c_str()); 2359 result.SetStatus(eReturnStatusFailed); 2360 return false; 2361 } 2362 2363 bool success = true; 2364 2365 // the order is not relevant here 2366 for (int i = argc - 1; i >= 0; i--) 2367 { 2368 const char* typeA = command.GetArgumentAtIndex(i); 2369 ConstString typeCS(typeA); 2370 2371 if (!typeCS) 2372 { 2373 result.AppendError("empty category name not allowed"); 2374 result.SetStatus(eReturnStatusFailed); 2375 return false; 2376 } 2377 if (!DataVisualization::Categories::Delete(typeCS)) 2378 success = false; // keep deleting even if we hit an error 2379 } 2380 if (success) 2381 { 2382 result.SetStatus(eReturnStatusSuccessFinishResult); 2383 return result.Succeeded(); 2384 } 2385 else 2386 { 2387 result.AppendError("cannot delete one or more categories\n"); 2388 result.SetStatus(eReturnStatusFailed); 2389 return false; 2390 } 2391 } 2392 }; 2393 2394 //------------------------------------------------------------------------- 2395 // CommandObjectTypeCategoryDisable 2396 //------------------------------------------------------------------------- 2397 2398 class CommandObjectTypeCategoryDisable : public CommandObjectParsed 2399 { 2400 class CommandOptions : public Options 2401 { 2402 public: 2403 CommandOptions (CommandInterpreter &interpreter) : 2404 Options (interpreter) 2405 { 2406 } 2407 2408 ~CommandOptions() override = default; 2409 2410 Error 2411 SetOptionValue (uint32_t option_idx, const char *option_arg) override 2412 { 2413 Error error; 2414 const int short_option = m_getopt_table[option_idx].val; 2415 2416 switch (short_option) 2417 { 2418 case 'l': 2419 if (option_arg) 2420 { 2421 m_language = Language::GetLanguageTypeFromString(option_arg); 2422 if (m_language == lldb::eLanguageTypeUnknown) 2423 error.SetErrorStringWithFormat ("unrecognized language '%s'", option_arg); 2424 } 2425 break; 2426 default: 2427 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2428 break; 2429 } 2430 2431 return error; 2432 } 2433 2434 void 2435 OptionParsingStarting () override 2436 { 2437 m_language = lldb::eLanguageTypeUnknown; 2438 } 2439 2440 const OptionDefinition* 2441 GetDefinitions () override 2442 { 2443 return g_option_table; 2444 } 2445 2446 // Options table: Required for subclasses of Options. 2447 2448 static OptionDefinition g_option_table[]; 2449 2450 // Instance variables to hold the values for command options. 2451 2452 lldb::LanguageType m_language; 2453 }; 2454 2455 CommandOptions m_options; 2456 2457 Options * 2458 GetOptions () override 2459 { 2460 return &m_options; 2461 } 2462 2463 public: 2464 CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) : 2465 CommandObjectParsed(interpreter, 2466 "type category disable", 2467 "Disable a category as a source of formatters.", 2468 nullptr), 2469 m_options(interpreter) 2470 { 2471 CommandArgumentEntry type_arg; 2472 CommandArgumentData type_style_arg; 2473 2474 type_style_arg.arg_type = eArgTypeName; 2475 type_style_arg.arg_repetition = eArgRepeatPlus; 2476 2477 type_arg.push_back (type_style_arg); 2478 2479 m_arguments.push_back (type_arg); 2480 } 2481 2482 ~CommandObjectTypeCategoryDisable() override = default; 2483 2484 protected: 2485 bool 2486 DoExecute (Args& command, CommandReturnObject &result) override 2487 { 2488 const size_t argc = command.GetArgumentCount(); 2489 2490 if (argc < 1 && 2491 m_options.m_language == lldb::eLanguageTypeUnknown) 2492 { 2493 result.AppendErrorWithFormat ("%s takes arguments and/or a language", m_cmd_name.c_str()); 2494 result.SetStatus(eReturnStatusFailed); 2495 return false; 2496 } 2497 2498 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0) 2499 { 2500 DataVisualization::Categories::DisableStar(); 2501 } 2502 else if (argc > 0) 2503 { 2504 // the order is not relevant here 2505 for (int i = argc - 1; i >= 0; i--) 2506 { 2507 const char* typeA = command.GetArgumentAtIndex(i); 2508 ConstString typeCS(typeA); 2509 2510 if (!typeCS) 2511 { 2512 result.AppendError("empty category name not allowed"); 2513 result.SetStatus(eReturnStatusFailed); 2514 return false; 2515 } 2516 DataVisualization::Categories::Disable(typeCS); 2517 } 2518 } 2519 2520 if (m_options.m_language != lldb::eLanguageTypeUnknown) 2521 DataVisualization::Categories::Disable(m_options.m_language); 2522 2523 result.SetStatus(eReturnStatusSuccessFinishResult); 2524 return result.Succeeded(); 2525 } 2526 }; 2527 2528 OptionDefinition 2529 CommandObjectTypeCategoryDisable::CommandOptions::g_option_table[] = 2530 { 2531 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Enable the category for this language."}, 2532 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 2533 }; 2534 2535 //------------------------------------------------------------------------- 2536 // CommandObjectTypeCategoryList 2537 //------------------------------------------------------------------------- 2538 2539 class CommandObjectTypeCategoryList : public CommandObjectParsed 2540 { 2541 public: 2542 CommandObjectTypeCategoryList (CommandInterpreter &interpreter) : 2543 CommandObjectParsed(interpreter, 2544 "type category list", 2545 "Provide a list of all existing categories.", 2546 nullptr) 2547 { 2548 CommandArgumentEntry type_arg; 2549 CommandArgumentData type_style_arg; 2550 2551 type_style_arg.arg_type = eArgTypeName; 2552 type_style_arg.arg_repetition = eArgRepeatOptional; 2553 2554 type_arg.push_back (type_style_arg); 2555 2556 m_arguments.push_back (type_arg); 2557 } 2558 2559 ~CommandObjectTypeCategoryList() override = default; 2560 2561 protected: 2562 bool 2563 DoExecute (Args& command, CommandReturnObject &result) override 2564 { 2565 const size_t argc = command.GetArgumentCount(); 2566 2567 std::unique_ptr<RegularExpression> regex; 2568 2569 if (argc == 1) 2570 { 2571 regex.reset(new RegularExpression()); 2572 const char* arg = command.GetArgumentAtIndex(0); 2573 if (!regex->Compile(arg)) 2574 { 2575 result.AppendErrorWithFormat("syntax error in category regular expression '%s'", arg); 2576 result.SetStatus(eReturnStatusFailed); 2577 return false; 2578 } 2579 } 2580 else if (argc != 0) 2581 { 2582 result.AppendErrorWithFormat ("%s takes 0 or one arg.\n", m_cmd_name.c_str()); 2583 result.SetStatus(eReturnStatusFailed); 2584 return false; 2585 } 2586 2587 DataVisualization::Categories::ForEach( [®ex, &result] (const lldb::TypeCategoryImplSP& category_sp) -> bool { 2588 if (regex) 2589 { 2590 bool escape = true; 2591 if (0 == strcmp(category_sp->GetName(), regex->GetText())) 2592 { 2593 escape = false; 2594 } 2595 else if (regex->Execute(category_sp->GetName())) 2596 { 2597 escape = false; 2598 } 2599 2600 if (escape) 2601 return true; 2602 } 2603 2604 result.GetOutputStream().Printf("Category: %s\n", category_sp->GetDescription().c_str()); 2605 2606 return true; 2607 }); 2608 2609 result.SetStatus(eReturnStatusSuccessFinishResult); 2610 return result.Succeeded(); 2611 } 2612 }; 2613 2614 //------------------------------------------------------------------------- 2615 // CommandObjectTypeFilterList 2616 //------------------------------------------------------------------------- 2617 2618 class CommandObjectTypeFilterList : public CommandObjectTypeFormatterList<TypeFilterImpl> 2619 { 2620 public: 2621 CommandObjectTypeFilterList (CommandInterpreter &interpreter) : 2622 CommandObjectTypeFormatterList(interpreter, 2623 "type filter list", 2624 "Show a list of current filters.") 2625 { 2626 } 2627 }; 2628 2629 #ifndef LLDB_DISABLE_PYTHON 2630 2631 //------------------------------------------------------------------------- 2632 // CommandObjectTypeSynthList 2633 //------------------------------------------------------------------------- 2634 2635 class CommandObjectTypeSynthList : public CommandObjectTypeFormatterList<SyntheticChildren> 2636 { 2637 public: 2638 CommandObjectTypeSynthList (CommandInterpreter &interpreter) : 2639 CommandObjectTypeFormatterList(interpreter, 2640 "type synthetic list", 2641 "Show a list of current synthetic providers.") 2642 { 2643 } 2644 }; 2645 2646 #endif // LLDB_DISABLE_PYTHON 2647 2648 //------------------------------------------------------------------------- 2649 // CommandObjectTypeFilterDelete 2650 //------------------------------------------------------------------------- 2651 2652 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete 2653 { 2654 public: 2655 CommandObjectTypeFilterDelete (CommandInterpreter &interpreter) : 2656 CommandObjectTypeFormatterDelete (interpreter, 2657 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2658 "type filter delete", 2659 "Delete an existing filter for a type.") 2660 { 2661 } 2662 2663 ~CommandObjectTypeFilterDelete() override = default; 2664 }; 2665 2666 #ifndef LLDB_DISABLE_PYTHON 2667 2668 //------------------------------------------------------------------------- 2669 // CommandObjectTypeSynthDelete 2670 //------------------------------------------------------------------------- 2671 2672 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete 2673 { 2674 public: 2675 CommandObjectTypeSynthDelete (CommandInterpreter &interpreter) : 2676 CommandObjectTypeFormatterDelete (interpreter, 2677 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 2678 "type synthetic delete", 2679 "Delete an existing synthetic provider for a type.") 2680 { 2681 } 2682 2683 ~CommandObjectTypeSynthDelete() override = default; 2684 }; 2685 2686 #endif // LLDB_DISABLE_PYTHON 2687 2688 //------------------------------------------------------------------------- 2689 // CommandObjectTypeFilterClear 2690 //------------------------------------------------------------------------- 2691 2692 class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear 2693 { 2694 public: 2695 CommandObjectTypeFilterClear (CommandInterpreter &interpreter) : 2696 CommandObjectTypeFormatterClear (interpreter, 2697 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2698 "type filter clear", 2699 "Delete all existing filter.") 2700 { 2701 } 2702 }; 2703 2704 #ifndef LLDB_DISABLE_PYTHON 2705 //------------------------------------------------------------------------- 2706 // CommandObjectTypeSynthClear 2707 //------------------------------------------------------------------------- 2708 2709 class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear 2710 { 2711 public: 2712 CommandObjectTypeSynthClear (CommandInterpreter &interpreter) : 2713 CommandObjectTypeFormatterClear (interpreter, 2714 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 2715 "type synthetic clear", 2716 "Delete all existing synthetic providers.") 2717 { 2718 } 2719 }; 2720 2721 bool 2722 CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result) 2723 { 2724 SynthAddOptions *options = new SynthAddOptions ( m_options.m_skip_pointers, 2725 m_options.m_skip_references, 2726 m_options.m_cascade, 2727 m_options.m_regex, 2728 m_options.m_category); 2729 2730 const size_t argc = command.GetArgumentCount(); 2731 2732 for (size_t i = 0; i < argc; i++) 2733 { 2734 const char* typeA = command.GetArgumentAtIndex(i); 2735 if (typeA && *typeA) 2736 options->m_target_types << typeA; 2737 else 2738 { 2739 result.AppendError("empty typenames not allowed"); 2740 result.SetStatus(eReturnStatusFailed); 2741 return false; 2742 } 2743 } 2744 2745 m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt 2746 *this, // IOHandlerDelegate 2747 true, // Run IOHandler in async mode 2748 options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions 2749 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2750 return result.Succeeded(); 2751 } 2752 2753 bool 2754 CommandObjectTypeSynthAdd::Execute_PythonClass (Args& command, CommandReturnObject &result) 2755 { 2756 const size_t argc = command.GetArgumentCount(); 2757 2758 if (argc < 1) 2759 { 2760 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 2761 result.SetStatus(eReturnStatusFailed); 2762 return false; 2763 } 2764 2765 if (m_options.m_class_name.empty() && !m_options.m_input_python) 2766 { 2767 result.AppendErrorWithFormat ("%s needs either a Python class name or -P to directly input Python code.\n", m_cmd_name.c_str()); 2768 result.SetStatus(eReturnStatusFailed); 2769 return false; 2770 } 2771 2772 SyntheticChildrenSP entry; 2773 2774 ScriptedSyntheticChildren* impl = new ScriptedSyntheticChildren(SyntheticChildren::Flags(). 2775 SetCascades(m_options.m_cascade). 2776 SetSkipPointers(m_options.m_skip_pointers). 2777 SetSkipReferences(m_options.m_skip_references), 2778 m_options.m_class_name.c_str()); 2779 2780 entry.reset(impl); 2781 2782 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 2783 2784 if (interpreter && !interpreter->CheckObjectExists(impl->GetPythonClassName())) 2785 result.AppendWarning("The provided class does not exist - please define it before attempting to use this synthetic provider"); 2786 2787 // now I have a valid provider, let's add it to every type 2788 2789 lldb::TypeCategoryImplSP category; 2790 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 2791 2792 Error error; 2793 2794 for (size_t i = 0; i < argc; i++) 2795 { 2796 const char* typeA = command.GetArgumentAtIndex(i); 2797 ConstString typeCS(typeA); 2798 if (typeCS) 2799 { 2800 if (!AddSynth(typeCS, 2801 entry, 2802 m_options.m_regex ? eRegexSynth : eRegularSynth, 2803 m_options.m_category, 2804 &error)) 2805 { 2806 result.AppendError(error.AsCString()); 2807 result.SetStatus(eReturnStatusFailed); 2808 return false; 2809 } 2810 } 2811 else 2812 { 2813 result.AppendError("empty typenames not allowed"); 2814 result.SetStatus(eReturnStatusFailed); 2815 return false; 2816 } 2817 } 2818 2819 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2820 return result.Succeeded(); 2821 } 2822 2823 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) : 2824 CommandObjectParsed(interpreter, 2825 "type synthetic add", 2826 "Add a new synthetic provider for a type.", 2827 nullptr), 2828 IOHandlerDelegateMultiline ("DONE"), 2829 m_options (interpreter) 2830 { 2831 CommandArgumentEntry type_arg; 2832 CommandArgumentData type_style_arg; 2833 2834 type_style_arg.arg_type = eArgTypeName; 2835 type_style_arg.arg_repetition = eArgRepeatPlus; 2836 2837 type_arg.push_back (type_style_arg); 2838 2839 m_arguments.push_back (type_arg); 2840 } 2841 2842 bool 2843 CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, 2844 SyntheticChildrenSP entry, 2845 SynthFormatType type, 2846 std::string category_name, 2847 Error* error) 2848 { 2849 lldb::TypeCategoryImplSP category; 2850 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); 2851 2852 if (type == eRegularSynth) 2853 { 2854 if (FixArrayTypeNameWithRegex (type_name)) 2855 type = eRegexSynth; 2856 } 2857 2858 if (category->AnyMatches(type_name, 2859 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2860 false)) 2861 { 2862 if (error) 2863 error->SetErrorStringWithFormat("cannot add synthetic for type %s when filter is defined in same category!", type_name.AsCString()); 2864 return false; 2865 } 2866 2867 if (type == eRegexSynth) 2868 { 2869 RegularExpressionSP typeRX(new RegularExpression()); 2870 if (!typeRX->Compile(type_name.GetCString())) 2871 { 2872 if (error) 2873 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 2874 return false; 2875 } 2876 2877 category->GetRegexTypeSyntheticsContainer()->Delete(type_name); 2878 category->GetRegexTypeSyntheticsContainer()->Add(typeRX, entry); 2879 2880 return true; 2881 } 2882 else 2883 { 2884 category->GetTypeSyntheticsContainer()->Add(type_name, entry); 2885 return true; 2886 } 2887 } 2888 2889 OptionDefinition 2890 CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] = 2891 { 2892 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, 2893 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 2894 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 2895 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 2896 { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children."}, 2897 { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children."}, 2898 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions."}, 2899 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 2900 }; 2901 2902 #endif // LLDB_DISABLE_PYTHON 2903 2904 class CommandObjectTypeFilterAdd : public CommandObjectParsed 2905 { 2906 private: 2907 class CommandOptions : public Options 2908 { 2909 typedef std::vector<std::string> option_vector; 2910 2911 public: 2912 CommandOptions (CommandInterpreter &interpreter) : 2913 Options (interpreter) 2914 { 2915 } 2916 2917 ~CommandOptions() override = default; 2918 2919 Error 2920 SetOptionValue (uint32_t option_idx, const char *option_arg) override 2921 { 2922 Error error; 2923 const int short_option = m_getopt_table[option_idx].val; 2924 bool success; 2925 2926 switch (short_option) 2927 { 2928 case 'C': 2929 m_cascade = Args::StringToBoolean(option_arg, true, &success); 2930 if (!success) 2931 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg); 2932 break; 2933 case 'c': 2934 m_expr_paths.push_back(option_arg); 2935 has_child_list = true; 2936 break; 2937 case 'p': 2938 m_skip_pointers = true; 2939 break; 2940 case 'r': 2941 m_skip_references = true; 2942 break; 2943 case 'w': 2944 m_category = std::string(option_arg); 2945 break; 2946 case 'x': 2947 m_regex = true; 2948 break; 2949 default: 2950 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2951 break; 2952 } 2953 2954 return error; 2955 } 2956 2957 void 2958 OptionParsingStarting () override 2959 { 2960 m_cascade = true; 2961 m_skip_pointers = false; 2962 m_skip_references = false; 2963 m_category = "default"; 2964 m_expr_paths.clear(); 2965 has_child_list = false; 2966 m_regex = false; 2967 } 2968 2969 const OptionDefinition* 2970 GetDefinitions () override 2971 { 2972 return g_option_table; 2973 } 2974 2975 // Options table: Required for subclasses of Options. 2976 2977 static OptionDefinition g_option_table[]; 2978 2979 // Instance variables to hold the values for command options. 2980 2981 bool m_cascade; 2982 bool m_skip_references; 2983 bool m_skip_pointers; 2984 bool m_input_python; 2985 option_vector m_expr_paths; 2986 std::string m_category; 2987 bool has_child_list; 2988 bool m_regex; 2989 2990 typedef option_vector::iterator ExpressionPathsIterator; 2991 }; 2992 2993 CommandOptions m_options; 2994 2995 Options * 2996 GetOptions () override 2997 { 2998 return &m_options; 2999 } 3000 3001 enum FilterFormatType 3002 { 3003 eRegularFilter, 3004 eRegexFilter 3005 }; 3006 3007 bool 3008 AddFilter(ConstString type_name, 3009 TypeFilterImplSP entry, 3010 FilterFormatType type, 3011 std::string category_name, 3012 Error* error) 3013 { 3014 lldb::TypeCategoryImplSP category; 3015 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); 3016 3017 if (type == eRegularFilter) 3018 { 3019 if (FixArrayTypeNameWithRegex (type_name)) 3020 type = eRegexFilter; 3021 } 3022 3023 if (category->AnyMatches(type_name, 3024 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 3025 false)) 3026 { 3027 if (error) 3028 error->SetErrorStringWithFormat("cannot add filter for type %s when synthetic is defined in same category!", type_name.AsCString()); 3029 return false; 3030 } 3031 3032 if (type == eRegexFilter) 3033 { 3034 RegularExpressionSP typeRX(new RegularExpression()); 3035 if (!typeRX->Compile(type_name.GetCString())) 3036 { 3037 if (error) 3038 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 3039 return false; 3040 } 3041 3042 category->GetRegexTypeFiltersContainer()->Delete(type_name); 3043 category->GetRegexTypeFiltersContainer()->Add(typeRX, entry); 3044 3045 return true; 3046 } 3047 else 3048 { 3049 category->GetTypeFiltersContainer()->Add(type_name, entry); 3050 return true; 3051 } 3052 } 3053 3054 public: 3055 CommandObjectTypeFilterAdd (CommandInterpreter &interpreter) : 3056 CommandObjectParsed(interpreter, 3057 "type filter add", 3058 "Add a new filter for a type.", 3059 nullptr), 3060 m_options (interpreter) 3061 { 3062 CommandArgumentEntry type_arg; 3063 CommandArgumentData type_style_arg; 3064 3065 type_style_arg.arg_type = eArgTypeName; 3066 type_style_arg.arg_repetition = eArgRepeatPlus; 3067 3068 type_arg.push_back (type_style_arg); 3069 3070 m_arguments.push_back (type_arg); 3071 3072 SetHelpLong( 3073 R"( 3074 The following examples of 'type filter add' refer to this code snippet for context: 3075 3076 class Foo { 3077 int a; 3078 int b; 3079 int c; 3080 int d; 3081 int e; 3082 int f; 3083 int g; 3084 int h; 3085 int i; 3086 } 3087 Foo my_foo; 3088 3089 Adding a simple filter: 3090 3091 (lldb) type filter add --child a --child g Foo 3092 (lldb) frame variable my_foo 3093 3094 )" "Produces output where only a and g are displayed. Other children of my_foo \ 3095 (b, c, d, e, f, h and i) are available by asking for them explicitly:" R"( 3096 3097 (lldb) frame variable my_foo.b my_foo.c my_foo.i 3098 3099 )" "The formatting option --raw on frame variable bypasses the filter, showing \ 3100 all children of my_foo as if no filter was defined:" R"( 3101 3102 (lldb) frame variable my_foo --raw)" 3103 ); 3104 } 3105 3106 ~CommandObjectTypeFilterAdd() override = default; 3107 3108 protected: 3109 bool 3110 DoExecute (Args& command, CommandReturnObject &result) override 3111 { 3112 const size_t argc = command.GetArgumentCount(); 3113 3114 if (argc < 1) 3115 { 3116 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 3117 result.SetStatus(eReturnStatusFailed); 3118 return false; 3119 } 3120 3121 if (m_options.m_expr_paths.empty()) 3122 { 3123 result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str()); 3124 result.SetStatus(eReturnStatusFailed); 3125 return false; 3126 } 3127 3128 TypeFilterImplSP entry(new TypeFilterImpl(SyntheticChildren::Flags().SetCascades(m_options.m_cascade). 3129 SetSkipPointers(m_options.m_skip_pointers). 3130 SetSkipReferences(m_options.m_skip_references))); 3131 3132 // go through the expression paths 3133 CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end(); 3134 3135 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++) 3136 entry->AddExpressionPath(*begin); 3137 3138 3139 // now I have a valid provider, let's add it to every type 3140 3141 lldb::TypeCategoryImplSP category; 3142 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 3143 3144 Error error; 3145 3146 WarnOnPotentialUnquotedUnsignedType(command, result); 3147 3148 for (size_t i = 0; i < argc; i++) 3149 { 3150 const char* typeA = command.GetArgumentAtIndex(i); 3151 ConstString typeCS(typeA); 3152 if (typeCS) 3153 { 3154 if (!AddFilter(typeCS, 3155 entry, 3156 m_options.m_regex ? eRegexFilter : eRegularFilter, 3157 m_options.m_category, 3158 &error)) 3159 { 3160 result.AppendError(error.AsCString()); 3161 result.SetStatus(eReturnStatusFailed); 3162 return false; 3163 } 3164 } 3165 else 3166 { 3167 result.AppendError("empty typenames not allowed"); 3168 result.SetStatus(eReturnStatusFailed); 3169 return false; 3170 } 3171 } 3172 3173 result.SetStatus(eReturnStatusSuccessFinishNoResult); 3174 return result.Succeeded(); 3175 } 3176 }; 3177 3178 OptionDefinition 3179 CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] = 3180 { 3181 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, 3182 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 3183 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 3184 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 3185 { LLDB_OPT_SET_ALL, false, "child", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view."}, 3186 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions."}, 3187 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 3188 }; 3189 3190 //---------------------------------------------------------------------- 3191 // "type lookup" 3192 //---------------------------------------------------------------------- 3193 class CommandObjectTypeLookup : public CommandObjectRaw 3194 { 3195 protected: 3196 class CommandOptions : public OptionGroup 3197 { 3198 public: 3199 CommandOptions () : 3200 OptionGroup(), 3201 m_show_help(false), 3202 m_language(eLanguageTypeUnknown) 3203 {} 3204 3205 ~CommandOptions() override = default; 3206 3207 uint32_t 3208 GetNumDefinitions () override 3209 { 3210 return 3; 3211 } 3212 3213 const OptionDefinition* 3214 GetDefinitions () override 3215 { 3216 return g_option_table; 3217 } 3218 3219 Error 3220 SetOptionValue (CommandInterpreter &interpreter, 3221 uint32_t option_idx, 3222 const char *option_value) override 3223 { 3224 Error error; 3225 3226 const int short_option = g_option_table[option_idx].short_option; 3227 3228 switch (short_option) 3229 { 3230 case 'h': 3231 m_show_help = true; 3232 break; 3233 3234 case 'l': 3235 m_language = Language::GetLanguageTypeFromString(option_value); 3236 break; 3237 3238 default: 3239 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 3240 break; 3241 } 3242 3243 return error; 3244 } 3245 3246 void 3247 OptionParsingStarting (CommandInterpreter &interpreter) override 3248 { 3249 m_show_help = false; 3250 m_language = eLanguageTypeUnknown; 3251 } 3252 3253 // Options table: Required for subclasses of Options. 3254 3255 static OptionDefinition g_option_table[]; 3256 bool m_show_help; 3257 lldb::LanguageType m_language; 3258 }; 3259 3260 OptionGroupOptions m_option_group; 3261 CommandOptions m_command_options; 3262 3263 public: 3264 CommandObjectTypeLookup (CommandInterpreter &interpreter) : 3265 CommandObjectRaw (interpreter, 3266 "type lookup", 3267 "Lookup a type by name in the select target.", 3268 "type lookup <typename>", 3269 eCommandRequiresTarget), 3270 m_option_group(interpreter), 3271 m_command_options() 3272 { 3273 m_option_group.Append(&m_command_options); 3274 m_option_group.Finalize(); 3275 } 3276 3277 ~CommandObjectTypeLookup() override = default; 3278 3279 Options * 3280 GetOptions () override 3281 { 3282 return &m_option_group; 3283 } 3284 3285 bool 3286 DoExecute (const char *raw_command_line, CommandReturnObject &result) override 3287 { 3288 if (!raw_command_line || !raw_command_line[0]) 3289 { 3290 result.SetError("type lookup cannot be invoked without a type name as argument"); 3291 return false; 3292 } 3293 3294 m_option_group.NotifyOptionParsingStarting(); 3295 3296 const char * name_of_type = nullptr; 3297 3298 if (raw_command_line[0] == '-') 3299 { 3300 // We have some options and these options MUST end with --. 3301 const char *end_options = nullptr; 3302 const char *s = raw_command_line; 3303 while (s && s[0]) 3304 { 3305 end_options = ::strstr (s, "--"); 3306 if (end_options) 3307 { 3308 end_options += 2; // Get past the "--" 3309 if (::isspace (end_options[0])) 3310 { 3311 name_of_type = end_options; 3312 while (::isspace (*name_of_type)) 3313 ++name_of_type; 3314 break; 3315 } 3316 } 3317 s = end_options; 3318 } 3319 3320 if (end_options) 3321 { 3322 Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line)); 3323 if (!ParseOptions (args, result)) 3324 return false; 3325 3326 Error error (m_option_group.NotifyOptionParsingFinished()); 3327 if (error.Fail()) 3328 { 3329 result.AppendError (error.AsCString()); 3330 result.SetStatus (eReturnStatusFailed); 3331 return false; 3332 } 3333 } 3334 } 3335 if (nullptr == name_of_type) 3336 name_of_type = raw_command_line; 3337 3338 TargetSP target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget()); 3339 const bool fill_all_in = true; 3340 ExecutionContext exe_ctx(target_sp.get(), fill_all_in); 3341 ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope(); 3342 3343 bool any_found = false; 3344 3345 std::vector<Language*> languages; 3346 3347 if (m_command_options.m_language == eLanguageTypeUnknown) 3348 { 3349 // FIXME: hardcoding languages is not good 3350 languages.push_back(Language::FindPlugin(eLanguageTypeObjC)); 3351 languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus)); 3352 } 3353 else 3354 { 3355 languages.push_back(Language::FindPlugin(m_command_options.m_language)); 3356 } 3357 3358 for (Language* language : languages) 3359 { 3360 if (!language) 3361 continue; 3362 3363 if (auto scavenger = language->GetTypeScavenger()) 3364 { 3365 Language::TypeScavenger::ResultSet search_results; 3366 if (scavenger->Find(best_scope, name_of_type, search_results) > 0) 3367 { 3368 for (const auto& search_result : search_results) 3369 { 3370 if (search_result && search_result->IsValid()) 3371 { 3372 any_found = true; 3373 search_result->DumpToStream(result.GetOutputStream(), this->m_command_options.m_show_help); 3374 } 3375 } 3376 } 3377 } 3378 } 3379 3380 result.SetStatus (any_found ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusSuccessFinishNoResult); 3381 return true; 3382 } 3383 }; 3384 3385 OptionDefinition 3386 CommandObjectTypeLookup::CommandOptions::g_option_table[] = 3387 { 3388 { LLDB_OPT_SET_ALL, false, "show-help", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display available help for types"}, 3389 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Which language's types should the search scope be"}, 3390 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 3391 }; 3392 3393 template <typename FormatterType> 3394 class CommandObjectFormatterInfo : public CommandObjectRaw 3395 { 3396 public: 3397 typedef std::function<typename FormatterType::SharedPointer(ValueObject&)> DiscoveryFunction; 3398 CommandObjectFormatterInfo (CommandInterpreter &interpreter, 3399 const char* formatter_name, 3400 DiscoveryFunction discovery_func) : 3401 CommandObjectRaw(interpreter, 3402 nullptr, 3403 nullptr, 3404 nullptr, 3405 eCommandRequiresFrame), 3406 m_formatter_name(formatter_name ? formatter_name : ""), 3407 m_discovery_function(discovery_func) 3408 { 3409 StreamString name; 3410 name.Printf("type %s info", formatter_name); 3411 SetCommandName(name.GetData()); 3412 StreamString help; 3413 help.Printf("This command evaluates the provided expression and shows which %s is applied to the resulting value (if any).", formatter_name); 3414 SetHelp(help.GetData()); 3415 StreamString syntax; 3416 syntax.Printf("type %s info <expr>", formatter_name); 3417 SetSyntax(syntax.GetData()); 3418 } 3419 3420 ~CommandObjectFormatterInfo() override = default; 3421 3422 protected: 3423 bool 3424 DoExecute (const char *command, CommandReturnObject &result) override 3425 { 3426 auto target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); 3427 auto frame_sp = target_sp->GetProcessSP()->GetThreadList().GetSelectedThread()->GetSelectedFrame(); 3428 ValueObjectSP result_valobj_sp; 3429 EvaluateExpressionOptions options; 3430 lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(command, frame_sp.get(), result_valobj_sp, options); 3431 if (expr_result == eExpressionCompleted && result_valobj_sp) 3432 { 3433 result_valobj_sp = result_valobj_sp->GetQualifiedRepresentationIfAvailable(target_sp->GetPreferDynamicValue(), target_sp->GetEnableSyntheticValue()); 3434 typename FormatterType::SharedPointer formatter_sp = m_discovery_function(*result_valobj_sp); 3435 if (formatter_sp) 3436 { 3437 std::string description(formatter_sp->GetDescription()); 3438 result.AppendMessageWithFormat("%s applied to (%s) %s is: %s\n", 3439 m_formatter_name.c_str(), 3440 result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"), 3441 command, 3442 description.c_str()); 3443 result.SetStatus(lldb::eReturnStatusSuccessFinishResult); 3444 } 3445 else 3446 { 3447 result.AppendMessageWithFormat("no %s applies to (%s) %s\n", 3448 m_formatter_name.c_str(), 3449 result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"), 3450 command); 3451 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 3452 } 3453 return true; 3454 } 3455 else 3456 { 3457 result.AppendError("failed to evaluate expression"); 3458 result.SetStatus(lldb::eReturnStatusFailed); 3459 return false; 3460 } 3461 } 3462 3463 private: 3464 std::string m_formatter_name; 3465 DiscoveryFunction m_discovery_function; 3466 }; 3467 3468 class CommandObjectTypeFormat : public CommandObjectMultiword 3469 { 3470 public: 3471 CommandObjectTypeFormat (CommandInterpreter &interpreter) : 3472 CommandObjectMultiword (interpreter, 3473 "type format", 3474 "A set of commands for editing variable value display options", 3475 "type format [<sub-command-options>] ") 3476 { 3477 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter))); 3478 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFormatClear (interpreter))); 3479 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter))); 3480 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFormatList (interpreter))); 3481 LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo<TypeFormatImpl>(interpreter, 3482 "format", 3483 [](ValueObject& valobj) -> TypeFormatImpl::SharedPointer { 3484 return valobj.GetValueFormat(); 3485 }))); 3486 } 3487 3488 ~CommandObjectTypeFormat() override = default; 3489 }; 3490 3491 #ifndef LLDB_DISABLE_PYTHON 3492 3493 class CommandObjectTypeSynth : public CommandObjectMultiword 3494 { 3495 public: 3496 CommandObjectTypeSynth (CommandInterpreter &interpreter) : 3497 CommandObjectMultiword (interpreter, 3498 "type synthetic", 3499 "A set of commands for operating on synthetic type representations", 3500 "type synthetic [<sub-command-options>] ") 3501 { 3502 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSynthAdd (interpreter))); 3503 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSynthClear (interpreter))); 3504 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSynthDelete (interpreter))); 3505 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSynthList (interpreter))); 3506 LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo<SyntheticChildren>(interpreter, 3507 "synthetic", 3508 [](ValueObject& valobj) -> SyntheticChildren::SharedPointer { 3509 return valobj.GetSyntheticChildren(); 3510 }))); 3511 } 3512 3513 ~CommandObjectTypeSynth() override = default; 3514 }; 3515 3516 #endif // LLDB_DISABLE_PYTHON 3517 3518 class CommandObjectTypeFilter : public CommandObjectMultiword 3519 { 3520 public: 3521 CommandObjectTypeFilter (CommandInterpreter &interpreter) : 3522 CommandObjectMultiword (interpreter, 3523 "type filter", 3524 "A set of commands for operating on type filters", 3525 "type synthetic [<sub-command-options>] ") 3526 { 3527 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeFilterAdd (interpreter))); 3528 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFilterClear (interpreter))); 3529 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFilterDelete (interpreter))); 3530 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFilterList (interpreter))); 3531 } 3532 3533 ~CommandObjectTypeFilter() override = default; 3534 }; 3535 3536 class CommandObjectTypeCategory : public CommandObjectMultiword 3537 { 3538 public: 3539 CommandObjectTypeCategory (CommandInterpreter &interpreter) : 3540 CommandObjectMultiword (interpreter, 3541 "type category", 3542 "A set of commands for operating on categories", 3543 "type category [<sub-command-options>] ") 3544 { 3545 LoadSubCommand ("define", CommandObjectSP (new CommandObjectTypeCategoryDefine (interpreter))); 3546 LoadSubCommand ("enable", CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter))); 3547 LoadSubCommand ("disable", CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter))); 3548 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter))); 3549 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeCategoryList (interpreter))); 3550 } 3551 3552 ~CommandObjectTypeCategory() override = default; 3553 }; 3554 3555 class CommandObjectTypeSummary : public CommandObjectMultiword 3556 { 3557 public: 3558 CommandObjectTypeSummary (CommandInterpreter &interpreter) : 3559 CommandObjectMultiword (interpreter, 3560 "type summary", 3561 "A set of commands for editing variable summary display options", 3562 "type summary [<sub-command-options>] ") 3563 { 3564 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter))); 3565 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter))); 3566 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter))); 3567 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); 3568 LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo<TypeSummaryImpl>(interpreter, 3569 "summary", 3570 [](ValueObject& valobj) -> TypeSummaryImpl::SharedPointer { 3571 return valobj.GetSummaryFormat(); 3572 }))); 3573 } 3574 3575 ~CommandObjectTypeSummary() override = default; 3576 }; 3577 3578 //------------------------------------------------------------------------- 3579 // CommandObjectType 3580 //------------------------------------------------------------------------- 3581 3582 CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) : 3583 CommandObjectMultiword (interpreter, 3584 "type", 3585 "A set of commands for operating on the type system", 3586 "type [<sub-command-options>]") 3587 { 3588 LoadSubCommand ("category", CommandObjectSP (new CommandObjectTypeCategory (interpreter))); 3589 LoadSubCommand ("filter", CommandObjectSP (new CommandObjectTypeFilter (interpreter))); 3590 LoadSubCommand ("format", CommandObjectSP (new CommandObjectTypeFormat (interpreter))); 3591 LoadSubCommand ("summary", CommandObjectSP (new CommandObjectTypeSummary (interpreter))); 3592 #ifndef LLDB_DISABLE_PYTHON 3593 LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter))); 3594 #endif // LLDB_DISABLE_PYTHON 3595 LoadSubCommand ("lookup", CommandObjectSP (new CommandObjectTypeLookup (interpreter))); 3596 } 3597 3598 CommandObjectType::~CommandObjectType() = default; 3599