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