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