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