1 //===-- CommandObjectType.cpp ----------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "CommandObjectType.h" 11 12 // C Includes 13 14 #include <ctype.h> 15 16 // C++ Includes 17 #include <functional> 18 19 #include "llvm/ADT/StringRef.h" 20 21 #include "lldb/Core/ConstString.h" 22 #include "lldb/Core/Debugger.h" 23 #include "lldb/Core/IOHandler.h" 24 #include "lldb/Core/RegularExpression.h" 25 #include "lldb/Core/State.h" 26 #include "lldb/Core/StringList.h" 27 #include "lldb/DataFormatters/DataVisualization.h" 28 #include "lldb/Interpreter/CommandInterpreter.h" 29 #include "lldb/Interpreter/CommandObject.h" 30 #include "lldb/Interpreter/CommandReturnObject.h" 31 #include "lldb/Interpreter/Options.h" 32 #include "lldb/Interpreter/OptionGroupFormat.h" 33 #include "lldb/Interpreter/OptionValueBoolean.h" 34 #include "lldb/Interpreter/OptionValueLanguage.h" 35 #include "lldb/Target/Language.h" 36 #include "lldb/Target/Process.h" 37 #include "lldb/Target/StackFrame.h" 38 #include "lldb/Target/Target.h" 39 #include "lldb/Target/Thread.h" 40 #include "lldb/Target/ThreadList.h" 41 42 using namespace lldb; 43 using namespace lldb_private; 44 45 46 class ScriptAddOptions 47 { 48 49 public: 50 51 TypeSummaryImpl::Flags m_flags; 52 53 StringList m_target_types; 54 55 bool m_regex; 56 57 ConstString m_name; 58 59 std::string m_category; 60 61 ScriptAddOptions(const TypeSummaryImpl::Flags& flags, 62 bool regx, 63 const ConstString& name, 64 std::string catg) : 65 m_flags(flags), 66 m_regex(regx), 67 m_name(name), 68 m_category(catg) 69 { 70 } 71 72 typedef std::shared_ptr<ScriptAddOptions> SharedPointer; 73 74 }; 75 76 class SynthAddOptions 77 { 78 79 public: 80 81 bool m_skip_pointers; 82 bool m_skip_references; 83 bool m_cascade; 84 bool m_regex; 85 StringList m_target_types; 86 87 std::string m_category; 88 89 SynthAddOptions(bool sptr, 90 bool sref, 91 bool casc, 92 bool regx, 93 std::string catg) : 94 m_skip_pointers(sptr), 95 m_skip_references(sref), 96 m_cascade(casc), 97 m_regex(regx), 98 m_target_types(), 99 m_category(catg) 100 { 101 } 102 103 typedef std::shared_ptr<SynthAddOptions> SharedPointer; 104 105 }; 106 107 static bool 108 WarnOnPotentialUnquotedUnsignedType (Args& command, CommandReturnObject &result) 109 { 110 for (unsigned idx = 0; idx < command.GetArgumentCount(); idx++) 111 { 112 const char* arg = command.GetArgumentAtIndex(idx); 113 if (idx+1 < command.GetArgumentCount()) 114 { 115 if (arg && 0 == strcmp(arg,"unsigned")) 116 { 117 const char* next = command.GetArgumentAtIndex(idx+1); 118 if (next && 119 (0 == strcmp(next, "int") || 120 0 == strcmp(next, "short") || 121 0 == strcmp(next, "char") || 122 0 == strcmp(next, "long"))) 123 { 124 result.AppendWarningWithFormat("%s %s being treated as two types. if you meant the combined type name use quotes, as in \"%s %s\"\n", 125 arg,next,arg,next); 126 return true; 127 } 128 } 129 } 130 } 131 return false; 132 } 133 134 class CommandObjectTypeSummaryAdd : 135 public CommandObjectParsed, 136 public IOHandlerDelegateMultiline 137 { 138 139 private: 140 141 class CommandOptions : public Options 142 { 143 public: 144 145 CommandOptions (CommandInterpreter &interpreter) : 146 Options (interpreter) 147 { 148 } 149 150 ~CommandOptions () override {} 151 152 Error 153 SetOptionValue (uint32_t option_idx, const char *option_arg) override; 154 155 void 156 OptionParsingStarting () override; 157 158 const OptionDefinition* 159 GetDefinitions () override 160 { 161 return g_option_table; 162 } 163 164 // Options table: Required for subclasses of Options. 165 166 static OptionDefinition g_option_table[]; 167 168 // Instance variables to hold the values for command options. 169 170 TypeSummaryImpl::Flags m_flags; 171 bool m_regex; 172 std::string m_format_string; 173 ConstString m_name; 174 std::string m_python_script; 175 std::string m_python_function; 176 bool m_is_add_script; 177 std::string m_category; 178 }; 179 180 CommandOptions m_options; 181 182 Options * 183 GetOptions () override 184 { 185 return &m_options; 186 } 187 188 bool 189 Execute_ScriptSummary (Args& command, CommandReturnObject &result); 190 191 bool 192 Execute_StringSummary (Args& command, CommandReturnObject &result); 193 194 public: 195 196 enum SummaryFormatType 197 { 198 eRegularSummary, 199 eRegexSummary, 200 eNamedSummary 201 }; 202 203 CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter); 204 205 ~CommandObjectTypeSummaryAdd () override 206 { 207 } 208 209 void 210 IOHandlerActivated (IOHandler &io_handler) override 211 { 212 static const char *g_summary_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" 213 "def function (valobj,internal_dict):\n" 214 " \"\"\"valobj: an SBValue which you want to provide a summary for\n" 215 " internal_dict: an LLDB support object not to be used\"\"\"\n"; 216 217 StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 218 if (output_sp) 219 { 220 output_sp->PutCString(g_summary_addreader_instructions); 221 output_sp->Flush(); 222 } 223 } 224 225 226 void 227 IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override 228 { 229 StreamFileSP error_sp = io_handler.GetErrorStreamFile(); 230 231 #ifndef LLDB_DISABLE_PYTHON 232 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 233 if (interpreter) 234 { 235 StringList lines; 236 lines.SplitIntoLines(data); 237 if (lines.GetSize() > 0) 238 { 239 ScriptAddOptions *options_ptr = ((ScriptAddOptions*)io_handler.GetUserData()); 240 if (options_ptr) 241 { 242 ScriptAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope 243 244 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 245 if (interpreter) 246 { 247 std::string funct_name_str; 248 if (interpreter->GenerateTypeScriptFunction (lines, funct_name_str)) 249 { 250 if (funct_name_str.empty()) 251 { 252 error_sp->Printf ("unable to obtain a valid function name from the script interpreter.\n"); 253 error_sp->Flush(); 254 } 255 else 256 { 257 // now I have a valid function name, let's add this as script for every type in the list 258 259 TypeSummaryImplSP script_format; 260 script_format.reset(new ScriptSummaryFormat(options->m_flags, 261 funct_name_str.c_str(), 262 lines.CopyList(" ").c_str())); 263 264 Error error; 265 266 for (size_t i = 0; i < options->m_target_types.GetSize(); i++) 267 { 268 const char *type_name = options->m_target_types.GetStringAtIndex(i); 269 CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name), 270 script_format, 271 (options->m_regex ? CommandObjectTypeSummaryAdd::eRegexSummary : CommandObjectTypeSummaryAdd::eRegularSummary), 272 options->m_category, 273 &error); 274 if (error.Fail()) 275 { 276 error_sp->Printf ("error: %s", error.AsCString()); 277 error_sp->Flush(); 278 } 279 } 280 281 if (options->m_name) 282 { 283 CommandObjectTypeSummaryAdd::AddSummary (options->m_name, 284 script_format, 285 CommandObjectTypeSummaryAdd::eNamedSummary, 286 options->m_category, 287 &error); 288 if (error.Fail()) 289 { 290 CommandObjectTypeSummaryAdd::AddSummary (options->m_name, 291 script_format, 292 CommandObjectTypeSummaryAdd::eNamedSummary, 293 options->m_category, 294 &error); 295 if (error.Fail()) 296 { 297 error_sp->Printf ("error: %s", error.AsCString()); 298 error_sp->Flush(); 299 } 300 } 301 else 302 { 303 error_sp->Printf ("error: %s", error.AsCString()); 304 error_sp->Flush(); 305 } 306 } 307 else 308 { 309 if (error.AsCString()) 310 { 311 error_sp->Printf ("error: %s", error.AsCString()); 312 error_sp->Flush(); 313 } 314 } 315 } 316 } 317 else 318 { 319 error_sp->Printf ("error: unable to generate a function.\n"); 320 error_sp->Flush(); 321 } 322 } 323 else 324 { 325 error_sp->Printf ("error: no script interpreter.\n"); 326 error_sp->Flush(); 327 } 328 } 329 else 330 { 331 error_sp->Printf ("error: internal synchronization information missing or invalid.\n"); 332 error_sp->Flush(); 333 } 334 } 335 else 336 { 337 error_sp->Printf ("error: empty function, didn't add python command.\n"); 338 error_sp->Flush(); 339 } 340 } 341 else 342 { 343 error_sp->Printf ("error: script interpreter missing, didn't add python command.\n"); 344 error_sp->Flush(); 345 } 346 #endif // #ifndef LLDB_DISABLE_PYTHON 347 io_handler.SetIsDone(true); 348 } 349 350 static bool 351 AddSummary(ConstString type_name, 352 lldb::TypeSummaryImplSP entry, 353 SummaryFormatType type, 354 std::string category, 355 Error* error = NULL); 356 protected: 357 bool 358 DoExecute (Args& command, CommandReturnObject &result) override; 359 360 }; 361 362 static const char *g_synth_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" 363 "You must define a Python class with these methods:\n" 364 " def __init__(self, valobj, dict):\n" 365 " def num_children(self):\n" 366 " def get_child_at_index(self, index):\n" 367 " def get_child_index(self, name):\n" 368 " def update(self):\n" 369 " '''Optional'''\n" 370 "class synthProvider:\n"; 371 372 class CommandObjectTypeSynthAdd : 373 public CommandObjectParsed, 374 public IOHandlerDelegateMultiline 375 { 376 377 private: 378 379 class CommandOptions : public Options 380 { 381 public: 382 383 CommandOptions (CommandInterpreter &interpreter) : 384 Options (interpreter) 385 { 386 } 387 388 ~CommandOptions () override {} 389 390 Error 391 SetOptionValue (uint32_t option_idx, const char *option_arg) override 392 { 393 Error error; 394 const int short_option = m_getopt_table[option_idx].val; 395 bool success; 396 397 switch (short_option) 398 { 399 case 'C': 400 m_cascade = Args::StringToBoolean(option_arg, true, &success); 401 if (!success) 402 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg); 403 break; 404 case 'P': 405 handwrite_python = true; 406 break; 407 case 'l': 408 m_class_name = std::string(option_arg); 409 is_class_based = true; 410 break; 411 case 'p': 412 m_skip_pointers = true; 413 break; 414 case 'r': 415 m_skip_references = true; 416 break; 417 case 'w': 418 m_category = std::string(option_arg); 419 break; 420 case 'x': 421 m_regex = true; 422 break; 423 default: 424 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 425 break; 426 } 427 428 return error; 429 } 430 431 void 432 OptionParsingStarting () override 433 { 434 m_cascade = true; 435 m_class_name = ""; 436 m_skip_pointers = false; 437 m_skip_references = false; 438 m_category = "default"; 439 is_class_based = false; 440 handwrite_python = false; 441 m_regex = false; 442 } 443 444 const OptionDefinition* 445 GetDefinitions () override 446 { 447 return g_option_table; 448 } 449 450 // Options table: Required for subclasses of Options. 451 452 static OptionDefinition g_option_table[]; 453 454 // Instance variables to hold the values for command options. 455 456 bool m_cascade; 457 bool m_skip_references; 458 bool m_skip_pointers; 459 std::string m_class_name; 460 bool m_input_python; 461 std::string m_category; 462 463 bool is_class_based; 464 465 bool handwrite_python; 466 467 bool m_regex; 468 469 }; 470 471 CommandOptions m_options; 472 473 Options * 474 GetOptions () override 475 { 476 return &m_options; 477 } 478 479 bool 480 Execute_HandwritePython (Args& command, CommandReturnObject &result); 481 482 bool 483 Execute_PythonClass (Args& command, CommandReturnObject &result); 484 485 protected: 486 bool 487 DoExecute (Args& command, CommandReturnObject &result) override 488 { 489 WarnOnPotentialUnquotedUnsignedType(command, result); 490 491 if (m_options.handwrite_python) 492 return Execute_HandwritePython(command, result); 493 else if (m_options.is_class_based) 494 return Execute_PythonClass(command, result); 495 else 496 { 497 result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line"); 498 result.SetStatus(eReturnStatusFailed); 499 return false; 500 } 501 } 502 503 void 504 IOHandlerActivated (IOHandler &io_handler) override 505 { 506 StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 507 if (output_sp) 508 { 509 output_sp->PutCString(g_synth_addreader_instructions); 510 output_sp->Flush(); 511 } 512 } 513 514 515 void 516 IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override 517 { 518 StreamFileSP error_sp = io_handler.GetErrorStreamFile(); 519 520 #ifndef LLDB_DISABLE_PYTHON 521 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 522 if (interpreter) 523 { 524 StringList lines; 525 lines.SplitIntoLines(data); 526 if (lines.GetSize() > 0) 527 { 528 SynthAddOptions *options_ptr = ((SynthAddOptions*)io_handler.GetUserData()); 529 if (options_ptr) 530 { 531 SynthAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope 532 533 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 534 if (interpreter) 535 { 536 std::string class_name_str; 537 if (interpreter->GenerateTypeSynthClass (lines, class_name_str)) 538 { 539 if (class_name_str.empty()) 540 { 541 error_sp->Printf ("error: unable to obtain a proper name for the class.\n"); 542 error_sp->Flush(); 543 } 544 else 545 { 546 // everything should be fine now, let's add the synth provider class 547 548 SyntheticChildrenSP synth_provider; 549 synth_provider.reset(new ScriptedSyntheticChildren(SyntheticChildren::Flags().SetCascades(options->m_cascade). 550 SetSkipPointers(options->m_skip_pointers). 551 SetSkipReferences(options->m_skip_references), 552 class_name_str.c_str())); 553 554 555 lldb::TypeCategoryImplSP category; 556 DataVisualization::Categories::GetCategory(ConstString(options->m_category.c_str()), category); 557 558 Error error; 559 560 for (size_t i = 0; i < options->m_target_types.GetSize(); i++) 561 { 562 const char *type_name = options->m_target_types.GetStringAtIndex(i); 563 ConstString const_type_name(type_name); 564 if (const_type_name) 565 { 566 if (!CommandObjectTypeSynthAdd::AddSynth(const_type_name, 567 synth_provider, 568 options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth, 569 options->m_category, 570 &error)) 571 { 572 error_sp->Printf("error: %s\n", error.AsCString()); 573 error_sp->Flush(); 574 break; 575 } 576 } 577 else 578 { 579 error_sp->Printf ("error: invalid type name.\n"); 580 error_sp->Flush(); 581 break; 582 } 583 } 584 } 585 } 586 else 587 { 588 error_sp->Printf ("error: unable to generate a class.\n"); 589 error_sp->Flush(); 590 } 591 } 592 else 593 { 594 error_sp->Printf ("error: no script interpreter.\n"); 595 error_sp->Flush(); 596 } 597 } 598 else 599 { 600 error_sp->Printf ("error: internal synchronization data missing.\n"); 601 error_sp->Flush(); 602 } 603 } 604 else 605 { 606 error_sp->Printf ("error: empty function, didn't add python command.\n"); 607 error_sp->Flush(); 608 } 609 } 610 else 611 { 612 error_sp->Printf ("error: script interpreter missing, didn't add python command.\n"); 613 error_sp->Flush(); 614 } 615 616 #endif // #ifndef LLDB_DISABLE_PYTHON 617 io_handler.SetIsDone(true); 618 } 619 620 public: 621 622 enum SynthFormatType 623 { 624 eRegularSynth, 625 eRegexSynth 626 }; 627 628 CommandObjectTypeSynthAdd (CommandInterpreter &interpreter); 629 630 ~CommandObjectTypeSynthAdd () override 631 { 632 } 633 634 static bool 635 AddSynth(ConstString type_name, 636 lldb::SyntheticChildrenSP entry, 637 SynthFormatType type, 638 std::string category_name, 639 Error* error); 640 }; 641 642 //------------------------------------------------------------------------- 643 // CommandObjectTypeFormatAdd 644 //------------------------------------------------------------------------- 645 646 class CommandObjectTypeFormatAdd : public CommandObjectParsed 647 { 648 649 private: 650 651 class CommandOptions : public OptionGroup 652 { 653 public: 654 655 CommandOptions () : 656 OptionGroup() 657 { 658 } 659 660 ~CommandOptions () override 661 { 662 } 663 664 uint32_t 665 GetNumDefinitions () override; 666 667 const OptionDefinition* 668 GetDefinitions () override 669 { 670 return g_option_table; 671 } 672 673 void 674 OptionParsingStarting (CommandInterpreter &interpreter) override 675 { 676 m_cascade = true; 677 m_skip_pointers = false; 678 m_skip_references = false; 679 m_regex = false; 680 m_category.assign("default"); 681 m_custom_type_name.clear(); 682 } 683 Error 684 SetOptionValue (CommandInterpreter &interpreter, 685 uint32_t option_idx, 686 const char *option_value) override 687 { 688 Error error; 689 const int short_option = g_option_table[option_idx].short_option; 690 bool success; 691 692 switch (short_option) 693 { 694 case 'C': 695 m_cascade = Args::StringToBoolean(option_value, true, &success); 696 if (!success) 697 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_value); 698 break; 699 case 'p': 700 m_skip_pointers = true; 701 break; 702 case 'w': 703 m_category.assign(option_value); 704 break; 705 case 'r': 706 m_skip_references = true; 707 break; 708 case 'x': 709 m_regex = true; 710 break; 711 case 't': 712 m_custom_type_name.assign(option_value); 713 break; 714 default: 715 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 716 break; 717 } 718 719 return error; 720 } 721 722 // Options table: Required for subclasses of Options. 723 724 static OptionDefinition g_option_table[]; 725 726 // Instance variables to hold the values for command options. 727 728 bool m_cascade; 729 bool m_skip_references; 730 bool m_skip_pointers; 731 bool m_regex; 732 std::string m_category; 733 std::string m_custom_type_name; 734 }; 735 736 OptionGroupOptions m_option_group; 737 OptionGroupFormat m_format_options; 738 CommandOptions m_command_options; 739 740 Options * 741 GetOptions () override 742 { 743 return &m_option_group; 744 } 745 746 public: 747 CommandObjectTypeFormatAdd (CommandInterpreter &interpreter) : 748 CommandObjectParsed (interpreter, 749 "type format add", 750 "Add a new formatting style for a type.", 751 NULL), 752 m_option_group (interpreter), 753 m_format_options (eFormatInvalid), 754 m_command_options () 755 { 756 CommandArgumentEntry type_arg; 757 CommandArgumentData type_style_arg; 758 759 type_style_arg.arg_type = eArgTypeName; 760 type_style_arg.arg_repetition = eArgRepeatPlus; 761 762 type_arg.push_back (type_style_arg); 763 764 m_arguments.push_back (type_arg); 765 766 SetHelpLong( 767 R"( 768 The following examples of 'type format add' refer to this code snippet for context: 769 770 typedef int Aint; 771 typedef float Afloat; 772 typedef Aint Bint; 773 typedef Afloat Bfloat; 774 775 Aint ix = 5; 776 Bint iy = 5; 777 778 Afloat fx = 3.14; 779 BFloat fy = 3.14; 780 781 Adding default formatting: 782 783 (lldb) type format add -f hex AInt 784 (lldb) frame variable iy 785 786 )" " Produces hexidecimal display of iy, because no formatter is available for Bint and \ 787 the one for Aint is used instead." R"( 788 789 To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains: 790 791 792 (lldb) type format add -f hex -C no AInt 793 794 Similar reasoning applies to this: 795 796 (lldb) type format add -f hex -C no float -p 797 798 )" " All float values and float references are now formatted as hexadecimal, but not \ 799 pointers to floats. Nor will it change the default display for Afloat and Bfloat objects." 800 ); 801 802 // Add the "--format" to all options groups 803 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1); 804 m_option_group.Append (&m_command_options); 805 m_option_group.Finalize(); 806 807 } 808 809 ~CommandObjectTypeFormatAdd () override 810 { 811 } 812 813 protected: 814 bool 815 DoExecute (Args& command, CommandReturnObject &result) override 816 { 817 const size_t argc = command.GetArgumentCount(); 818 819 if (argc < 1) 820 { 821 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 822 result.SetStatus(eReturnStatusFailed); 823 return false; 824 } 825 826 const Format format = m_format_options.GetFormat(); 827 if (format == eFormatInvalid && m_command_options.m_custom_type_name.empty()) 828 { 829 result.AppendErrorWithFormat ("%s needs a valid format.\n", m_cmd_name.c_str()); 830 result.SetStatus(eReturnStatusFailed); 831 return false; 832 } 833 834 TypeFormatImplSP entry; 835 836 if (m_command_options.m_custom_type_name.empty()) 837 entry.reset(new TypeFormatImpl_Format(format, 838 TypeFormatImpl::Flags().SetCascades(m_command_options.m_cascade). 839 SetSkipPointers(m_command_options.m_skip_pointers). 840 SetSkipReferences(m_command_options.m_skip_references))); 841 else 842 entry.reset(new TypeFormatImpl_EnumType(ConstString(m_command_options.m_custom_type_name.c_str()), 843 TypeFormatImpl::Flags().SetCascades(m_command_options.m_cascade). 844 SetSkipPointers(m_command_options.m_skip_pointers). 845 SetSkipReferences(m_command_options.m_skip_references))); 846 847 // now I have a valid format, let's add it to every type 848 849 TypeCategoryImplSP category_sp; 850 DataVisualization::Categories::GetCategory(ConstString(m_command_options.m_category), category_sp); 851 if (!category_sp) 852 return false; 853 854 WarnOnPotentialUnquotedUnsignedType(command, result); 855 856 for (size_t i = 0; i < argc; i++) 857 { 858 const char* typeA = command.GetArgumentAtIndex(i); 859 ConstString typeCS(typeA); 860 if (typeCS) 861 { 862 if (m_command_options.m_regex) 863 { 864 RegularExpressionSP typeRX(new RegularExpression()); 865 if (!typeRX->Compile(typeCS.GetCString())) 866 { 867 result.AppendError("regex format error (maybe this is not really a regex?)"); 868 result.SetStatus(eReturnStatusFailed); 869 return false; 870 } 871 category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS); 872 category_sp->GetRegexTypeFormatsContainer()->Add(typeRX, entry); 873 } 874 else 875 category_sp->GetTypeFormatsContainer()->Add(typeCS, entry); 876 } 877 else 878 { 879 result.AppendError("empty typenames not allowed"); 880 result.SetStatus(eReturnStatusFailed); 881 return false; 882 } 883 } 884 885 result.SetStatus(eReturnStatusSuccessFinishNoResult); 886 return result.Succeeded(); 887 } 888 }; 889 890 OptionDefinition 891 CommandObjectTypeFormatAdd::CommandOptions::g_option_table[] = 892 { 893 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 894 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, 895 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 896 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 897 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, 898 { LLDB_OPT_SET_2, false, "type", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Format variables as if they were of this type."}, 899 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 900 }; 901 902 903 uint32_t 904 CommandObjectTypeFormatAdd::CommandOptions::GetNumDefinitions () 905 { 906 return sizeof(g_option_table) / sizeof (OptionDefinition); 907 } 908 909 910 //------------------------------------------------------------------------- 911 // CommandObjectTypeFormatDelete 912 //------------------------------------------------------------------------- 913 914 class CommandObjectTypeFormatDelete : public CommandObjectParsed 915 { 916 private: 917 class CommandOptions : public Options 918 { 919 public: 920 921 CommandOptions (CommandInterpreter &interpreter) : 922 Options (interpreter) 923 { 924 } 925 926 ~CommandOptions () override {} 927 928 Error 929 SetOptionValue (uint32_t option_idx, const char *option_arg) override 930 { 931 Error error; 932 const int short_option = m_getopt_table[option_idx].val; 933 934 switch (short_option) 935 { 936 case 'a': 937 m_delete_all = true; 938 break; 939 case 'w': 940 m_category = std::string(option_arg); 941 break; 942 default: 943 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 944 break; 945 } 946 947 return error; 948 } 949 950 void 951 OptionParsingStarting () override 952 { 953 m_delete_all = false; 954 m_category = "default"; 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 972 }; 973 974 CommandOptions m_options; 975 976 Options * 977 GetOptions () override 978 { 979 return &m_options; 980 } 981 982 static bool 983 PerCategoryCallback(void* param, 984 const lldb::TypeCategoryImplSP& category_sp) 985 { 986 ConstString *name = (ConstString*)param; 987 category_sp->Delete(*name, eFormatCategoryItemValue | eFormatCategoryItemRegexValue); 988 return true; 989 } 990 991 public: 992 CommandObjectTypeFormatDelete (CommandInterpreter &interpreter) : 993 CommandObjectParsed (interpreter, 994 "type format delete", 995 "Delete an existing formatting style for a type.", 996 NULL), 997 m_options(interpreter) 998 { 999 CommandArgumentEntry type_arg; 1000 CommandArgumentData type_style_arg; 1001 1002 type_style_arg.arg_type = eArgTypeName; 1003 type_style_arg.arg_repetition = eArgRepeatPlain; 1004 1005 type_arg.push_back (type_style_arg); 1006 1007 m_arguments.push_back (type_arg); 1008 1009 } 1010 1011 ~CommandObjectTypeFormatDelete () override 1012 { 1013 } 1014 1015 protected: 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::LoopThrough(PerCategoryCallback, &typeCS); 1041 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1042 return result.Succeeded(); 1043 } 1044 1045 lldb::TypeCategoryImplSP category; 1046 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 1047 1048 bool delete_category = category->Delete(typeCS, 1049 eFormatCategoryItemValue | eFormatCategoryItemRegexValue); 1050 1051 if (delete_category) 1052 { 1053 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1054 return result.Succeeded(); 1055 } 1056 else 1057 { 1058 result.AppendErrorWithFormat ("no custom format for %s.\n", typeA); 1059 result.SetStatus(eReturnStatusFailed); 1060 return false; 1061 } 1062 1063 } 1064 1065 }; 1066 1067 OptionDefinition 1068 CommandObjectTypeFormatDelete::CommandOptions::g_option_table[] = 1069 { 1070 { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Delete from every category."}, 1071 { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Delete from given category."}, 1072 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 1073 }; 1074 1075 //------------------------------------------------------------------------- 1076 // CommandObjectTypeFormatClear 1077 //------------------------------------------------------------------------- 1078 1079 class CommandObjectTypeFormatClear : public CommandObjectParsed 1080 { 1081 private: 1082 1083 class CommandOptions : public Options 1084 { 1085 public: 1086 1087 CommandOptions (CommandInterpreter &interpreter) : 1088 Options (interpreter) 1089 { 1090 } 1091 1092 ~CommandOptions () override {} 1093 1094 Error 1095 SetOptionValue (uint32_t option_idx, const char *option_arg) override 1096 { 1097 Error error; 1098 const int short_option = m_getopt_table[option_idx].val; 1099 1100 switch (short_option) 1101 { 1102 case 'a': 1103 m_delete_all = true; 1104 break; 1105 default: 1106 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1107 break; 1108 } 1109 1110 return error; 1111 } 1112 1113 void 1114 OptionParsingStarting () override 1115 { 1116 m_delete_all = false; 1117 } 1118 1119 const OptionDefinition* 1120 GetDefinitions () override 1121 { 1122 return g_option_table; 1123 } 1124 1125 // Options table: Required for subclasses of Options. 1126 1127 static OptionDefinition g_option_table[]; 1128 1129 // Instance variables to hold the values for command options. 1130 1131 bool m_delete_all; 1132 bool m_delete_named; 1133 }; 1134 1135 CommandOptions m_options; 1136 1137 Options * 1138 GetOptions () override 1139 { 1140 return &m_options; 1141 } 1142 1143 static bool 1144 PerCategoryCallback(void* param, 1145 const lldb::TypeCategoryImplSP& cate) 1146 { 1147 cate->GetTypeFormatsContainer()->Clear(); 1148 cate->GetRegexTypeFormatsContainer()->Clear(); 1149 return true; 1150 1151 } 1152 1153 public: 1154 CommandObjectTypeFormatClear (CommandInterpreter &interpreter) : 1155 CommandObjectParsed (interpreter, 1156 "type format clear", 1157 "Delete all existing format styles.", 1158 NULL), 1159 m_options(interpreter) 1160 { 1161 } 1162 1163 ~CommandObjectTypeFormatClear () override 1164 { 1165 } 1166 1167 protected: 1168 bool 1169 DoExecute (Args& command, CommandReturnObject &result) override 1170 { 1171 if (m_options.m_delete_all) 1172 DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL); 1173 1174 else 1175 { 1176 lldb::TypeCategoryImplSP category; 1177 if (command.GetArgumentCount() > 0) 1178 { 1179 const char* cat_name = command.GetArgumentAtIndex(0); 1180 ConstString cat_nameCS(cat_name); 1181 DataVisualization::Categories::GetCategory(cat_nameCS, category); 1182 } 1183 else 1184 DataVisualization::Categories::GetCategory(ConstString(NULL), category); 1185 category->Clear(eFormatCategoryItemValue | eFormatCategoryItemRegexValue); 1186 } 1187 1188 result.SetStatus(eReturnStatusSuccessFinishResult); 1189 return result.Succeeded(); 1190 } 1191 1192 }; 1193 1194 OptionDefinition 1195 CommandObjectTypeFormatClear::CommandOptions::g_option_table[] = 1196 { 1197 { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Clear every category."}, 1198 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 1199 }; 1200 1201 //------------------------------------------------------------------------- 1202 // CommandObjectTypeFormatList 1203 //------------------------------------------------------------------------- 1204 1205 bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeFormatImplSP& entry); 1206 bool CommandObjectTypeRXFormatList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const lldb::TypeFormatImplSP& entry); 1207 1208 class CommandObjectTypeFormatList; 1209 1210 struct CommandObjectTypeFormatList_LoopCallbackParam { 1211 CommandObjectTypeFormatList* self; 1212 CommandReturnObject* result; 1213 RegularExpression* regex; 1214 RegularExpression* cate_regex; 1215 CommandObjectTypeFormatList_LoopCallbackParam(CommandObjectTypeFormatList* S, CommandReturnObject* R, 1216 RegularExpression* X = NULL, RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {} 1217 }; 1218 1219 class CommandObjectTypeFormatList : public CommandObjectParsed 1220 { 1221 class CommandOptions : public Options 1222 { 1223 public: 1224 1225 CommandOptions (CommandInterpreter &interpreter) : 1226 Options (interpreter) 1227 { 1228 } 1229 1230 ~CommandOptions () override {} 1231 1232 Error 1233 SetOptionValue (uint32_t option_idx, const char *option_arg) override 1234 { 1235 Error error; 1236 const int short_option = m_getopt_table[option_idx].val; 1237 1238 switch (short_option) 1239 { 1240 case 'w': 1241 m_category_regex = std::string(option_arg); 1242 break; 1243 default: 1244 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1245 break; 1246 } 1247 1248 return error; 1249 } 1250 1251 void 1252 OptionParsingStarting () override 1253 { 1254 m_category_regex = ""; 1255 } 1256 1257 const OptionDefinition* 1258 GetDefinitions () override 1259 { 1260 return g_option_table; 1261 } 1262 1263 // Options table: Required for subclasses of Options. 1264 1265 static OptionDefinition g_option_table[]; 1266 1267 // Instance variables to hold the values for command options. 1268 1269 std::string m_category_regex; 1270 1271 }; 1272 1273 CommandOptions m_options; 1274 1275 Options * 1276 GetOptions () override 1277 { 1278 return &m_options; 1279 } 1280 1281 public: 1282 CommandObjectTypeFormatList (CommandInterpreter &interpreter) : 1283 CommandObjectParsed (interpreter, 1284 "type format list", 1285 "Show a list of current formatting styles.", 1286 NULL), 1287 m_options(interpreter) 1288 { 1289 CommandArgumentEntry type_arg; 1290 CommandArgumentData type_style_arg; 1291 1292 type_style_arg.arg_type = eArgTypeName; 1293 type_style_arg.arg_repetition = eArgRepeatOptional; 1294 1295 type_arg.push_back (type_style_arg); 1296 1297 m_arguments.push_back (type_arg); 1298 } 1299 1300 ~CommandObjectTypeFormatList () override 1301 { 1302 } 1303 1304 protected: 1305 bool 1306 DoExecute (Args& command, CommandReturnObject &result) override 1307 { 1308 const size_t argc = command.GetArgumentCount(); 1309 1310 CommandObjectTypeFormatList_LoopCallbackParam *param; 1311 RegularExpression* cate_regex = 1312 m_options.m_category_regex.empty() ? NULL : 1313 new RegularExpression(m_options.m_category_regex.c_str()); 1314 1315 if (argc == 1) 1316 { 1317 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 1318 regex->Compile(command.GetArgumentAtIndex(0)); 1319 param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result,regex,cate_regex); 1320 } 1321 else 1322 param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result,NULL,cate_regex); 1323 1324 DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); 1325 delete param; 1326 1327 if (cate_regex) 1328 delete cate_regex; 1329 1330 result.SetStatus(eReturnStatusSuccessFinishResult); 1331 return result.Succeeded(); 1332 } 1333 1334 private: 1335 1336 static bool 1337 PerCategoryCallback(void* param_vp, 1338 const lldb::TypeCategoryImplSP& cate) 1339 { 1340 1341 CommandObjectTypeFormatList_LoopCallbackParam* param = 1342 (CommandObjectTypeFormatList_LoopCallbackParam*)param_vp; 1343 CommandReturnObject* result = param->result; 1344 1345 const char* cate_name = cate->GetName(); 1346 1347 // if the category is disabled or empty and there is no regex, just skip it 1348 if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemValue | eFormatCategoryItemRegexValue) == 0) && param->cate_regex == NULL) 1349 return true; 1350 1351 // if we have a regex and this category does not match it, just skip it 1352 if(param->cate_regex != NULL && strcmp(cate_name,param->cate_regex->GetText()) != 0 && param->cate_regex->Execute(cate_name) == false) 1353 return true; 1354 1355 result->GetOutputStream().Printf("-----------------------\nCategory: %s\n-----------------------\n", cate->GetDescription().c_str()); 1356 1357 cate->GetTypeFormatsContainer()->LoopThrough(CommandObjectTypeFormatList_LoopCallback, param_vp); 1358 1359 if (cate->GetRegexTypeSummariesContainer()->GetCount() > 0) 1360 { 1361 result->GetOutputStream().Printf("Regex-based summaries (slower):\n"); 1362 cate->GetRegexTypeFormatsContainer()->LoopThrough(CommandObjectTypeRXFormatList_LoopCallback, param_vp); 1363 } 1364 return true; 1365 } 1366 1367 1368 bool 1369 LoopCallback (const char* type, 1370 const lldb::TypeFormatImplSP& entry, 1371 RegularExpression* regex, 1372 CommandReturnObject *result) 1373 { 1374 if (regex == NULL || strcmp(type,regex->GetText()) == 0 || regex->Execute(type)) 1375 result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); 1376 return true; 1377 } 1378 1379 friend bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeFormatImplSP& entry); 1380 friend bool CommandObjectTypeRXFormatList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const lldb::TypeFormatImplSP& entry); 1381 1382 }; 1383 1384 bool 1385 CommandObjectTypeFormatList_LoopCallback ( 1386 void* pt2self, 1387 ConstString type, 1388 const lldb::TypeFormatImplSP& entry) 1389 { 1390 CommandObjectTypeFormatList_LoopCallbackParam* param = (CommandObjectTypeFormatList_LoopCallbackParam*)pt2self; 1391 return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result); 1392 } 1393 1394 bool 1395 CommandObjectTypeRXFormatList_LoopCallback ( 1396 void* pt2self, 1397 lldb::RegularExpressionSP regex, 1398 const lldb::TypeFormatImplSP& entry) 1399 { 1400 CommandObjectTypeFormatList_LoopCallbackParam* param = (CommandObjectTypeFormatList_LoopCallbackParam*)pt2self; 1401 return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); 1402 } 1403 1404 OptionDefinition 1405 CommandObjectTypeFormatList::CommandOptions::g_option_table[] = 1406 { 1407 { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."}, 1408 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 1409 }; 1410 1411 #ifndef LLDB_DISABLE_PYTHON 1412 1413 //------------------------------------------------------------------------- 1414 // CommandObjectTypeSummaryAdd 1415 //------------------------------------------------------------------------- 1416 1417 #endif // #ifndef LLDB_DISABLE_PYTHON 1418 1419 Error 1420 CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) 1421 { 1422 Error error; 1423 const int short_option = m_getopt_table[option_idx].val; 1424 bool success; 1425 1426 switch (short_option) 1427 { 1428 case 'C': 1429 m_flags.SetCascades(Args::StringToBoolean(option_arg, true, &success)); 1430 if (!success) 1431 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg); 1432 break; 1433 case 'e': 1434 m_flags.SetDontShowChildren(false); 1435 break; 1436 case 'h': 1437 m_flags.SetHideEmptyAggregates(true); 1438 break; 1439 case 'v': 1440 m_flags.SetDontShowValue(true); 1441 break; 1442 case 'c': 1443 m_flags.SetShowMembersOneLiner(true); 1444 break; 1445 case 's': 1446 m_format_string = std::string(option_arg); 1447 break; 1448 case 'p': 1449 m_flags.SetSkipPointers(true); 1450 break; 1451 case 'r': 1452 m_flags.SetSkipReferences(true); 1453 break; 1454 case 'x': 1455 m_regex = true; 1456 break; 1457 case 'n': 1458 m_name.SetCString(option_arg); 1459 break; 1460 case 'o': 1461 m_python_script = std::string(option_arg); 1462 m_is_add_script = true; 1463 break; 1464 case 'F': 1465 m_python_function = std::string(option_arg); 1466 m_is_add_script = true; 1467 break; 1468 case 'P': 1469 m_is_add_script = true; 1470 break; 1471 case 'w': 1472 m_category = std::string(option_arg); 1473 break; 1474 case 'O': 1475 m_flags.SetHideItemNames(true); 1476 break; 1477 default: 1478 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1479 break; 1480 } 1481 1482 return error; 1483 } 1484 1485 void 1486 CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting () 1487 { 1488 m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false); 1489 m_flags.SetShowMembersOneLiner(false).SetSkipPointers(false).SetSkipReferences(false).SetHideItemNames(false); 1490 1491 m_regex = false; 1492 m_name.Clear(); 1493 m_python_script = ""; 1494 m_python_function = ""; 1495 m_format_string = ""; 1496 m_is_add_script = false; 1497 m_category = "default"; 1498 } 1499 1500 1501 1502 #ifndef LLDB_DISABLE_PYTHON 1503 1504 bool 1505 CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturnObject &result) 1506 { 1507 const size_t argc = command.GetArgumentCount(); 1508 1509 if (argc < 1 && !m_options.m_name) 1510 { 1511 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 1512 result.SetStatus(eReturnStatusFailed); 1513 return false; 1514 } 1515 1516 TypeSummaryImplSP script_format; 1517 1518 if (!m_options.m_python_function.empty()) // we have a Python function ready to use 1519 { 1520 const char *funct_name = m_options.m_python_function.c_str(); 1521 if (!funct_name || !funct_name[0]) 1522 { 1523 result.AppendError ("function name empty.\n"); 1524 result.SetStatus (eReturnStatusFailed); 1525 return false; 1526 } 1527 1528 std::string code = (" " + m_options.m_python_function + "(valobj,internal_dict)"); 1529 1530 script_format.reset(new ScriptSummaryFormat(m_options.m_flags, 1531 funct_name, 1532 code.c_str())); 1533 1534 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 1535 1536 if (interpreter && interpreter->CheckObjectExists(funct_name) == false) 1537 result.AppendWarningWithFormat("The provided function \"%s\" does not exist - " 1538 "please define it before attempting to use this summary.\n", 1539 funct_name); 1540 } 1541 else if (!m_options.m_python_script.empty()) // we have a quick 1-line script, just use it 1542 { 1543 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 1544 if (!interpreter) 1545 { 1546 result.AppendError ("script interpreter missing - unable to generate function wrapper.\n"); 1547 result.SetStatus (eReturnStatusFailed); 1548 return false; 1549 } 1550 StringList funct_sl; 1551 funct_sl << m_options.m_python_script.c_str(); 1552 std::string funct_name_str; 1553 if (!interpreter->GenerateTypeScriptFunction (funct_sl, 1554 funct_name_str)) 1555 { 1556 result.AppendError ("unable to generate function wrapper.\n"); 1557 result.SetStatus (eReturnStatusFailed); 1558 return false; 1559 } 1560 if (funct_name_str.empty()) 1561 { 1562 result.AppendError ("script interpreter failed to generate a valid function name.\n"); 1563 result.SetStatus (eReturnStatusFailed); 1564 return false; 1565 } 1566 1567 std::string code = " " + m_options.m_python_script; 1568 1569 script_format.reset(new ScriptSummaryFormat(m_options.m_flags, 1570 funct_name_str.c_str(), 1571 code.c_str())); 1572 } 1573 else 1574 { 1575 // Use an IOHandler to grab Python code from the user 1576 ScriptAddOptions *options = new ScriptAddOptions(m_options.m_flags, 1577 m_options.m_regex, 1578 m_options.m_name, 1579 m_options.m_category); 1580 1581 for (size_t i = 0; i < argc; i++) 1582 { 1583 const char* typeA = command.GetArgumentAtIndex(i); 1584 if (typeA && *typeA) 1585 options->m_target_types << typeA; 1586 else 1587 { 1588 result.AppendError("empty typenames not allowed"); 1589 result.SetStatus(eReturnStatusFailed); 1590 return false; 1591 } 1592 } 1593 1594 m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt 1595 *this, // IOHandlerDelegate 1596 true, // Run IOHandler in async mode 1597 options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions 1598 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1599 1600 return result.Succeeded(); 1601 } 1602 1603 // if I am here, script_format must point to something good, so I can add that 1604 // as a script summary to all interested parties 1605 1606 Error error; 1607 1608 for (size_t i = 0; i < command.GetArgumentCount(); i++) 1609 { 1610 const char *type_name = command.GetArgumentAtIndex(i); 1611 CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name), 1612 script_format, 1613 (m_options.m_regex ? eRegexSummary : eRegularSummary), 1614 m_options.m_category, 1615 &error); 1616 if (error.Fail()) 1617 { 1618 result.AppendError(error.AsCString()); 1619 result.SetStatus(eReturnStatusFailed); 1620 return false; 1621 } 1622 } 1623 1624 if (m_options.m_name) 1625 { 1626 AddSummary(m_options.m_name, script_format, eNamedSummary, m_options.m_category, &error); 1627 if (error.Fail()) 1628 { 1629 result.AppendError(error.AsCString()); 1630 result.AppendError("added to types, but not given a name"); 1631 result.SetStatus(eReturnStatusFailed); 1632 return false; 1633 } 1634 } 1635 1636 return result.Succeeded(); 1637 } 1638 1639 #endif 1640 1641 1642 bool 1643 CommandObjectTypeSummaryAdd::Execute_StringSummary (Args& command, CommandReturnObject &result) 1644 { 1645 const size_t argc = command.GetArgumentCount(); 1646 1647 if (argc < 1 && !m_options.m_name) 1648 { 1649 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 1650 result.SetStatus(eReturnStatusFailed); 1651 return false; 1652 } 1653 1654 if (!m_options.m_flags.GetShowMembersOneLiner() && m_options.m_format_string.empty()) 1655 { 1656 result.AppendError("empty summary strings not allowed"); 1657 result.SetStatus(eReturnStatusFailed); 1658 return false; 1659 } 1660 1661 const char* format_cstr = (m_options.m_flags.GetShowMembersOneLiner() ? "" : m_options.m_format_string.c_str()); 1662 1663 // ${var%S} is an endless recursion, prevent it 1664 if (strcmp(format_cstr, "${var%S}") == 0) 1665 { 1666 result.AppendError("recursive summary not allowed"); 1667 result.SetStatus(eReturnStatusFailed); 1668 return false; 1669 } 1670 1671 Error error; 1672 1673 lldb::TypeSummaryImplSP entry(new StringSummaryFormat(m_options.m_flags, 1674 format_cstr)); 1675 1676 if (error.Fail()) 1677 { 1678 result.AppendError(error.AsCString()); 1679 result.SetStatus(eReturnStatusFailed); 1680 return false; 1681 } 1682 1683 // now I have a valid format, let's add it to every type 1684 1685 for (size_t i = 0; i < argc; i++) 1686 { 1687 const char* typeA = command.GetArgumentAtIndex(i); 1688 if (!typeA || typeA[0] == '\0') 1689 { 1690 result.AppendError("empty typenames not allowed"); 1691 result.SetStatus(eReturnStatusFailed); 1692 return false; 1693 } 1694 ConstString typeCS(typeA); 1695 1696 AddSummary(typeCS, 1697 entry, 1698 (m_options.m_regex ? eRegexSummary : eRegularSummary), 1699 m_options.m_category, 1700 &error); 1701 1702 if (error.Fail()) 1703 { 1704 result.AppendError(error.AsCString()); 1705 result.SetStatus(eReturnStatusFailed); 1706 return false; 1707 } 1708 } 1709 1710 if (m_options.m_name) 1711 { 1712 AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category, &error); 1713 if (error.Fail()) 1714 { 1715 result.AppendError(error.AsCString()); 1716 result.AppendError("added to types, but not given a name"); 1717 result.SetStatus(eReturnStatusFailed); 1718 return false; 1719 } 1720 } 1721 1722 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1723 return result.Succeeded(); 1724 } 1725 1726 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter) : 1727 CommandObjectParsed (interpreter, 1728 "type summary add", 1729 "Add a new summary style for a type.", 1730 NULL), 1731 IOHandlerDelegateMultiline ("DONE"), 1732 m_options (interpreter) 1733 { 1734 CommandArgumentEntry type_arg; 1735 CommandArgumentData type_style_arg; 1736 1737 type_style_arg.arg_type = eArgTypeName; 1738 type_style_arg.arg_repetition = eArgRepeatPlus; 1739 1740 type_arg.push_back (type_style_arg); 1741 1742 m_arguments.push_back (type_arg); 1743 1744 SetHelpLong( 1745 R"( 1746 The following examples of 'type summary add' refer to this code snippet for context: 1747 1748 struct JustADemo 1749 { 1750 int* ptr; 1751 float value; 1752 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {} 1753 }; 1754 JustADemo demo_instance(42, 3.14); 1755 1756 typedef JustADemo NewDemo; 1757 NewDemo new_demo_instance(42, 3.14); 1758 1759 (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo 1760 1761 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42" 1762 1763 (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo 1764 1765 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14" 1766 1767 )" "Alternatively, you could define formatting for all pointers to integers and \ 1768 rely on that when formatting JustADemo to obtain the same result:" R"( 1769 1770 (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *" 1771 (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo 1772 1773 )" "Type summaries are automatically applied to derived typedefs, so the examples \ 1774 above apply to both JustADemo and NewDemo. The cascade option can be used to \ 1775 suppress this behavior:" R"( 1776 1777 (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no 1778 1779 The summary will now be used for values of JustADemo but not NewDemo. 1780 1781 )" "By default summaries are shown for pointers and references to values of the \ 1782 specified type. To suppress formatting for pointers use the -p option, or apply \ 1783 the corresponding -r option to suppress formatting for references:" R"( 1784 1785 (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo 1786 1787 )" "One-line summaries including all fields in a type can be inferred without supplying an \ 1788 explicit summary string by passing the -c option:" R"( 1789 1790 (lldb) type summary add -c JustADemo 1791 (lldb) frame variable demo_instance 1792 (ptr=<address>, value=3.14) 1793 1794 )" "Type summaries normally suppress the nested display of individual fields. To \ 1795 supply a summary to supplement the default structure add the -e option:" R"( 1796 1797 (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo 1798 1799 )" "Now when displaying JustADemo values the int* is displayed, followed by the \ 1800 standard LLDB sequence of children, one per line:" R"( 1801 1802 *ptr = 42 { 1803 ptr = <address> 1804 value = 3.14 1805 } 1806 1807 )" "You can also add summaries written in Python. These scripts use lldb public API to \ 1808 gather information from your variables and produce a meaningful summary. To start a \ 1809 multi-line script use the -P option. The function declaration will be displayed along with \ 1810 a comment describing the two arguments. End your script with the word 'DONE' on a line by \ 1811 itself:" R"( 1812 1813 (lldb) type summary add JustADemo -P 1814 def function (valobj,internal_dict): 1815 """valobj: an SBValue which you want to provide a summary for 1816 internal_dict: an LLDB support object not to be used""" 1817 value = valobj.GetChildMemberWithName('value'); 1818 return 'My value is ' + value.GetValue(); 1819 DONE 1820 1821 Alternatively, the -o option can be used when providing a simple one-line Python script: 1822 1823 (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")" 1824 ); 1825 } 1826 1827 bool 1828 CommandObjectTypeSummaryAdd::DoExecute (Args& command, CommandReturnObject &result) 1829 { 1830 WarnOnPotentialUnquotedUnsignedType(command, result); 1831 1832 if (m_options.m_is_add_script) 1833 { 1834 #ifndef LLDB_DISABLE_PYTHON 1835 return Execute_ScriptSummary(command, result); 1836 #else 1837 result.AppendError ("python is disabled"); 1838 result.SetStatus(eReturnStatusFailed); 1839 return false; 1840 #endif 1841 } 1842 1843 return Execute_StringSummary(command, result); 1844 } 1845 1846 static bool 1847 FixArrayTypeNameWithRegex (ConstString &type_name) 1848 { 1849 llvm::StringRef type_name_ref(type_name.GetStringRef()); 1850 1851 if (type_name_ref.endswith("[]")) 1852 { 1853 std::string type_name_str(type_name.GetCString()); 1854 type_name_str.resize(type_name_str.length()-2); 1855 if (type_name_str.back() != ' ') 1856 type_name_str.append(" \\[[0-9]+\\]"); 1857 else 1858 type_name_str.append("\\[[0-9]+\\]"); 1859 type_name.SetCString(type_name_str.c_str()); 1860 return true; 1861 } 1862 return false; 1863 } 1864 1865 bool 1866 CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, 1867 TypeSummaryImplSP entry, 1868 SummaryFormatType type, 1869 std::string category_name, 1870 Error* error) 1871 { 1872 lldb::TypeCategoryImplSP category; 1873 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); 1874 1875 if (type == eRegularSummary) 1876 { 1877 if (FixArrayTypeNameWithRegex (type_name)) 1878 type = eRegexSummary; 1879 } 1880 1881 if (type == eRegexSummary) 1882 { 1883 RegularExpressionSP typeRX(new RegularExpression()); 1884 if (!typeRX->Compile(type_name.GetCString())) 1885 { 1886 if (error) 1887 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 1888 return false; 1889 } 1890 1891 category->GetRegexTypeSummariesContainer()->Delete(type_name); 1892 category->GetRegexTypeSummariesContainer()->Add(typeRX, entry); 1893 1894 return true; 1895 } 1896 else if (type == eNamedSummary) 1897 { 1898 // system named summaries do not exist (yet?) 1899 DataVisualization::NamedSummaryFormats::Add(type_name,entry); 1900 return true; 1901 } 1902 else 1903 { 1904 category->GetTypeSummariesContainer()->Add(type_name, entry); 1905 return true; 1906 } 1907 } 1908 1909 OptionDefinition 1910 CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = 1911 { 1912 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 1913 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, 1914 { 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."}, 1915 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 1916 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 1917 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, 1918 { LLDB_OPT_SET_1 , true, "inline-children", 'c', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "If true, inline all child values into summary string."}, 1919 { LLDB_OPT_SET_1 , false, "omit-names", 'O', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "If true, omit value names in the summary display."}, 1920 { LLDB_OPT_SET_2 , true, "summary-string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeSummaryString, "Summary string used to display text and object contents."}, 1921 { 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."}, 1922 { 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."}, 1923 { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Input Python code to use for this type manually."}, 1924 { 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."}, 1925 { 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."}, 1926 { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "A name for this summary string."}, 1927 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 1928 }; 1929 1930 1931 //------------------------------------------------------------------------- 1932 // CommandObjectTypeSummaryDelete 1933 //------------------------------------------------------------------------- 1934 1935 class CommandObjectTypeSummaryDelete : public CommandObjectParsed 1936 { 1937 private: 1938 class CommandOptions : public Options 1939 { 1940 public: 1941 1942 CommandOptions (CommandInterpreter &interpreter) : 1943 Options (interpreter) 1944 { 1945 } 1946 1947 ~CommandOptions () override {} 1948 1949 Error 1950 SetOptionValue (uint32_t option_idx, const char *option_arg) override 1951 { 1952 Error error; 1953 const int short_option = m_getopt_table[option_idx].val; 1954 1955 switch (short_option) 1956 { 1957 case 'a': 1958 m_delete_all = true; 1959 break; 1960 case 'w': 1961 m_category = std::string(option_arg); 1962 break; 1963 default: 1964 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1965 break; 1966 } 1967 1968 return error; 1969 } 1970 1971 void 1972 OptionParsingStarting () override 1973 { 1974 m_delete_all = false; 1975 m_category = "default"; 1976 } 1977 1978 const OptionDefinition* 1979 GetDefinitions () override 1980 { 1981 return g_option_table; 1982 } 1983 1984 // Options table: Required for subclasses of Options. 1985 1986 static OptionDefinition g_option_table[]; 1987 1988 // Instance variables to hold the values for command options. 1989 1990 bool m_delete_all; 1991 std::string m_category; 1992 1993 }; 1994 1995 CommandOptions m_options; 1996 1997 Options * 1998 GetOptions () override 1999 { 2000 return &m_options; 2001 } 2002 2003 static bool 2004 PerCategoryCallback(void* param, 2005 const lldb::TypeCategoryImplSP& category_sp) 2006 { 2007 ConstString *name = (ConstString*)param; 2008 category_sp->Delete(*name, eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary); 2009 return true; 2010 } 2011 2012 public: 2013 CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) : 2014 CommandObjectParsed (interpreter, 2015 "type summary delete", 2016 "Delete an existing summary style for a type.", 2017 NULL), 2018 m_options(interpreter) 2019 { 2020 CommandArgumentEntry type_arg; 2021 CommandArgumentData type_style_arg; 2022 2023 type_style_arg.arg_type = eArgTypeName; 2024 type_style_arg.arg_repetition = eArgRepeatPlain; 2025 2026 type_arg.push_back (type_style_arg); 2027 2028 m_arguments.push_back (type_arg); 2029 2030 } 2031 2032 ~CommandObjectTypeSummaryDelete () override 2033 { 2034 } 2035 2036 protected: 2037 bool 2038 DoExecute (Args& command, CommandReturnObject &result) override 2039 { 2040 const size_t argc = command.GetArgumentCount(); 2041 2042 if (argc != 1) 2043 { 2044 result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); 2045 result.SetStatus(eReturnStatusFailed); 2046 return false; 2047 } 2048 2049 const char* typeA = command.GetArgumentAtIndex(0); 2050 ConstString typeCS(typeA); 2051 2052 if (!typeCS) 2053 { 2054 result.AppendError("empty typenames not allowed"); 2055 result.SetStatus(eReturnStatusFailed); 2056 return false; 2057 } 2058 2059 if (m_options.m_delete_all) 2060 { 2061 DataVisualization::Categories::LoopThrough(PerCategoryCallback, &typeCS); 2062 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2063 return result.Succeeded(); 2064 } 2065 2066 lldb::TypeCategoryImplSP category; 2067 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 2068 2069 bool delete_category = category->Delete(typeCS, 2070 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary); 2071 bool delete_named = DataVisualization::NamedSummaryFormats::Delete(typeCS); 2072 2073 if (delete_category || delete_named) 2074 { 2075 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2076 return result.Succeeded(); 2077 } 2078 else 2079 { 2080 result.AppendErrorWithFormat ("no custom summary for %s.\n", typeA); 2081 result.SetStatus(eReturnStatusFailed); 2082 return false; 2083 } 2084 2085 } 2086 }; 2087 2088 OptionDefinition 2089 CommandObjectTypeSummaryDelete::CommandOptions::g_option_table[] = 2090 { 2091 { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Delete from every category."}, 2092 { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Delete from given category."}, 2093 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 2094 }; 2095 2096 class CommandObjectTypeSummaryClear : public CommandObjectParsed 2097 { 2098 private: 2099 2100 class CommandOptions : public Options 2101 { 2102 public: 2103 2104 CommandOptions (CommandInterpreter &interpreter) : 2105 Options (interpreter) 2106 { 2107 } 2108 2109 ~CommandOptions () override {} 2110 2111 Error 2112 SetOptionValue (uint32_t option_idx, const char *option_arg) override 2113 { 2114 Error error; 2115 const int short_option = m_getopt_table[option_idx].val; 2116 2117 switch (short_option) 2118 { 2119 case 'a': 2120 m_delete_all = true; 2121 break; 2122 default: 2123 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2124 break; 2125 } 2126 2127 return error; 2128 } 2129 2130 void 2131 OptionParsingStarting () override 2132 { 2133 m_delete_all = false; 2134 } 2135 2136 const OptionDefinition* 2137 GetDefinitions () override 2138 { 2139 return g_option_table; 2140 } 2141 2142 // Options table: Required for subclasses of Options. 2143 2144 static OptionDefinition g_option_table[]; 2145 2146 // Instance variables to hold the values for command options. 2147 2148 bool m_delete_all; 2149 bool m_delete_named; 2150 }; 2151 2152 CommandOptions m_options; 2153 2154 Options * 2155 GetOptions () override 2156 { 2157 return &m_options; 2158 } 2159 2160 static bool 2161 PerCategoryCallback(void* param, 2162 const lldb::TypeCategoryImplSP& cate) 2163 { 2164 cate->GetTypeSummariesContainer()->Clear(); 2165 cate->GetRegexTypeSummariesContainer()->Clear(); 2166 return true; 2167 2168 } 2169 2170 public: 2171 CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) : 2172 CommandObjectParsed (interpreter, 2173 "type summary clear", 2174 "Delete all existing summary styles.", 2175 NULL), 2176 m_options(interpreter) 2177 { 2178 } 2179 2180 ~CommandObjectTypeSummaryClear () override 2181 { 2182 } 2183 2184 protected: 2185 bool 2186 DoExecute (Args& command, CommandReturnObject &result) override 2187 { 2188 2189 if (m_options.m_delete_all) 2190 DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL); 2191 2192 else 2193 { 2194 lldb::TypeCategoryImplSP category; 2195 if (command.GetArgumentCount() > 0) 2196 { 2197 const char* cat_name = command.GetArgumentAtIndex(0); 2198 ConstString cat_nameCS(cat_name); 2199 DataVisualization::Categories::GetCategory(cat_nameCS, category); 2200 } 2201 else 2202 DataVisualization::Categories::GetCategory(ConstString(NULL), category); 2203 category->Clear(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary); 2204 } 2205 2206 DataVisualization::NamedSummaryFormats::Clear(); 2207 2208 result.SetStatus(eReturnStatusSuccessFinishResult); 2209 return result.Succeeded(); 2210 } 2211 2212 }; 2213 2214 OptionDefinition 2215 CommandObjectTypeSummaryClear::CommandOptions::g_option_table[] = 2216 { 2217 { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Clear every category."}, 2218 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 2219 }; 2220 2221 //------------------------------------------------------------------------- 2222 // CommandObjectTypeSummaryList 2223 //------------------------------------------------------------------------- 2224 2225 bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, ConstString type, const StringSummaryFormat::SharedPointer& entry); 2226 bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const StringSummaryFormat::SharedPointer& entry); 2227 2228 class CommandObjectTypeSummaryList; 2229 2230 struct CommandObjectTypeSummaryList_LoopCallbackParam { 2231 CommandObjectTypeSummaryList* self; 2232 CommandReturnObject* result; 2233 RegularExpression* regex; 2234 RegularExpression* cate_regex; 2235 CommandObjectTypeSummaryList_LoopCallbackParam(CommandObjectTypeSummaryList* S, CommandReturnObject* R, 2236 RegularExpression* X = NULL, 2237 RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {} 2238 }; 2239 2240 class CommandObjectTypeSummaryList : public CommandObjectParsed 2241 { 2242 2243 class CommandOptions : public Options 2244 { 2245 public: 2246 2247 CommandOptions (CommandInterpreter &interpreter) : 2248 Options (interpreter) 2249 { 2250 } 2251 2252 ~CommandOptions () override {} 2253 2254 Error 2255 SetOptionValue (uint32_t option_idx, const char *option_arg) override 2256 { 2257 Error error; 2258 const int short_option = m_getopt_table[option_idx].val; 2259 2260 switch (short_option) 2261 { 2262 case 'w': 2263 m_category_regex = std::string(option_arg); 2264 break; 2265 default: 2266 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2267 break; 2268 } 2269 2270 return error; 2271 } 2272 2273 void 2274 OptionParsingStarting () override 2275 { 2276 m_category_regex = ""; 2277 } 2278 2279 const OptionDefinition* 2280 GetDefinitions () override 2281 { 2282 return g_option_table; 2283 } 2284 2285 // Options table: Required for subclasses of Options. 2286 2287 static OptionDefinition g_option_table[]; 2288 2289 // Instance variables to hold the values for command options. 2290 2291 std::string m_category_regex; 2292 2293 }; 2294 2295 CommandOptions m_options; 2296 2297 Options * 2298 GetOptions () override 2299 { 2300 return &m_options; 2301 } 2302 2303 public: 2304 CommandObjectTypeSummaryList (CommandInterpreter &interpreter) : 2305 CommandObjectParsed (interpreter, 2306 "type summary list", 2307 "Show a list of current summary styles.", 2308 NULL), 2309 m_options(interpreter) 2310 { 2311 CommandArgumentEntry type_arg; 2312 CommandArgumentData type_style_arg; 2313 2314 type_style_arg.arg_type = eArgTypeName; 2315 type_style_arg.arg_repetition = eArgRepeatOptional; 2316 2317 type_arg.push_back (type_style_arg); 2318 2319 m_arguments.push_back (type_arg); 2320 } 2321 2322 ~CommandObjectTypeSummaryList () override 2323 { 2324 } 2325 2326 protected: 2327 bool 2328 DoExecute (Args& command, CommandReturnObject &result) override 2329 { 2330 const size_t argc = command.GetArgumentCount(); 2331 2332 CommandObjectTypeSummaryList_LoopCallbackParam *param; 2333 RegularExpression* cate_regex = 2334 m_options.m_category_regex.empty() ? NULL : 2335 new RegularExpression(m_options.m_category_regex.c_str()); 2336 2337 if (argc == 1) 2338 { 2339 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 2340 regex->Compile(command.GetArgumentAtIndex(0)); 2341 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex,cate_regex); 2342 } 2343 else 2344 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,NULL,cate_regex); 2345 2346 DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); 2347 delete param; 2348 2349 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) 2350 { 2351 result.GetOutputStream().Printf("Named summaries:\n"); 2352 if (argc == 1) 2353 { 2354 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 2355 regex->Compile(command.GetArgumentAtIndex(0)); 2356 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex); 2357 } 2358 else 2359 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result); 2360 DataVisualization::NamedSummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param); 2361 delete param; 2362 } 2363 2364 if (cate_regex) 2365 delete cate_regex; 2366 2367 result.SetStatus(eReturnStatusSuccessFinishResult); 2368 return result.Succeeded(); 2369 } 2370 2371 private: 2372 2373 static bool 2374 PerCategoryCallback(void* param_vp, 2375 const lldb::TypeCategoryImplSP& cate) 2376 { 2377 2378 CommandObjectTypeSummaryList_LoopCallbackParam* param = 2379 (CommandObjectTypeSummaryList_LoopCallbackParam*)param_vp; 2380 CommandReturnObject* result = param->result; 2381 2382 const char* cate_name = cate->GetName(); 2383 2384 // if the category is disabled or empty and there is no regex, just skip it 2385 if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary) == 0) && param->cate_regex == NULL) 2386 return true; 2387 2388 // if we have a regex and this category does not match it, just skip it 2389 if(param->cate_regex != NULL && strcmp(cate_name,param->cate_regex->GetText()) != 0 && param->cate_regex->Execute(cate_name) == false) 2390 return true; 2391 2392 result->GetOutputStream().Printf("-----------------------\nCategory: %s\n-----------------------\n", cate->GetDescription().c_str()); 2393 2394 cate->GetTypeSummariesContainer()->LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param_vp); 2395 2396 if (cate->GetRegexTypeSummariesContainer()->GetCount() > 0) 2397 { 2398 result->GetOutputStream().Printf("Regex-based summaries (slower):\n"); 2399 cate->GetRegexTypeSummariesContainer()->LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, param_vp); 2400 } 2401 return true; 2402 } 2403 2404 2405 bool 2406 LoopCallback (const char* type, 2407 const lldb::TypeSummaryImplSP& entry, 2408 RegularExpression* regex, 2409 CommandReturnObject *result) 2410 { 2411 if (regex == NULL || strcmp(type,regex->GetText()) == 0 || regex->Execute(type)) 2412 result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); 2413 return true; 2414 } 2415 2416 friend bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeSummaryImplSP& entry); 2417 friend bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const lldb::TypeSummaryImplSP& entry); 2418 }; 2419 2420 bool 2421 CommandObjectTypeSummaryList_LoopCallback ( 2422 void* pt2self, 2423 ConstString type, 2424 const lldb::TypeSummaryImplSP& entry) 2425 { 2426 CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self; 2427 return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result); 2428 } 2429 2430 bool 2431 CommandObjectTypeRXSummaryList_LoopCallback ( 2432 void* pt2self, 2433 lldb::RegularExpressionSP regex, 2434 const lldb::TypeSummaryImplSP& entry) 2435 { 2436 CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self; 2437 return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); 2438 } 2439 2440 OptionDefinition 2441 CommandObjectTypeSummaryList::CommandOptions::g_option_table[] = 2442 { 2443 { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."}, 2444 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 2445 }; 2446 2447 //------------------------------------------------------------------------- 2448 // CommandObjectTypeCategoryDefine 2449 //------------------------------------------------------------------------- 2450 2451 class CommandObjectTypeCategoryDefine : public CommandObjectParsed 2452 { 2453 2454 class CommandOptions : public Options 2455 { 2456 public: 2457 2458 CommandOptions (CommandInterpreter &interpreter) : 2459 Options (interpreter), 2460 m_define_enabled(false,false), 2461 m_cate_language(eLanguageTypeUnknown,eLanguageTypeUnknown) 2462 { 2463 } 2464 2465 ~CommandOptions () override {} 2466 2467 Error 2468 SetOptionValue (uint32_t option_idx, const char *option_arg) override 2469 { 2470 Error error; 2471 const int short_option = m_getopt_table[option_idx].val; 2472 2473 switch (short_option) 2474 { 2475 case 'e': 2476 m_define_enabled.SetValueFromString("true"); 2477 break; 2478 case 'l': 2479 error = m_cate_language.SetValueFromString(option_arg); 2480 break; 2481 default: 2482 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2483 break; 2484 } 2485 2486 return error; 2487 } 2488 2489 void 2490 OptionParsingStarting () override 2491 { 2492 m_define_enabled.Clear(); 2493 m_cate_language.Clear(); 2494 } 2495 2496 const OptionDefinition* 2497 GetDefinitions () override 2498 { 2499 return g_option_table; 2500 } 2501 2502 // Options table: Required for subclasses of Options. 2503 2504 static OptionDefinition g_option_table[]; 2505 2506 // Instance variables to hold the values for command options. 2507 2508 OptionValueBoolean m_define_enabled; 2509 OptionValueLanguage m_cate_language; 2510 2511 2512 }; 2513 2514 CommandOptions m_options; 2515 2516 Options * 2517 GetOptions () override 2518 { 2519 return &m_options; 2520 } 2521 2522 public: 2523 CommandObjectTypeCategoryDefine (CommandInterpreter &interpreter) : 2524 CommandObjectParsed (interpreter, 2525 "type category define", 2526 "Define a new category as a source of formatters.", 2527 NULL), 2528 m_options(interpreter) 2529 { 2530 CommandArgumentEntry type_arg; 2531 CommandArgumentData type_style_arg; 2532 2533 type_style_arg.arg_type = eArgTypeName; 2534 type_style_arg.arg_repetition = eArgRepeatPlus; 2535 2536 type_arg.push_back (type_style_arg); 2537 2538 m_arguments.push_back (type_arg); 2539 2540 } 2541 2542 ~CommandObjectTypeCategoryDefine () override 2543 { 2544 } 2545 2546 protected: 2547 bool 2548 DoExecute (Args& command, CommandReturnObject &result) override 2549 { 2550 const size_t argc = command.GetArgumentCount(); 2551 2552 if (argc < 1) 2553 { 2554 result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str()); 2555 result.SetStatus(eReturnStatusFailed); 2556 return false; 2557 } 2558 2559 for (size_t i = 0; i < argc; i++) 2560 { 2561 const char* cateName = command.GetArgumentAtIndex(i); 2562 TypeCategoryImplSP category_sp; 2563 if (DataVisualization::Categories::GetCategory(ConstString(cateName), category_sp) && category_sp) 2564 { 2565 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue()); 2566 if (m_options.m_define_enabled.GetCurrentValue()) 2567 DataVisualization::Categories::Enable(category_sp, TypeCategoryMap::Default); 2568 } 2569 } 2570 2571 result.SetStatus(eReturnStatusSuccessFinishResult); 2572 return result.Succeeded(); 2573 } 2574 2575 }; 2576 2577 OptionDefinition 2578 CommandObjectTypeCategoryDefine::CommandOptions::g_option_table[] = 2579 { 2580 { LLDB_OPT_SET_ALL, false, "enabled", 'e', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "If specified, this category will be created enabled."}, 2581 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Specify the language that this category is supported for."}, 2582 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 2583 }; 2584 2585 //------------------------------------------------------------------------- 2586 // CommandObjectTypeCategoryEnable 2587 //------------------------------------------------------------------------- 2588 2589 class CommandObjectTypeCategoryEnable : public CommandObjectParsed 2590 { 2591 class CommandOptions : public Options 2592 { 2593 public: 2594 2595 CommandOptions (CommandInterpreter &interpreter) : 2596 Options (interpreter) 2597 { 2598 } 2599 2600 ~CommandOptions () override {} 2601 2602 Error 2603 SetOptionValue (uint32_t option_idx, const char *option_arg) override 2604 { 2605 Error error; 2606 const int short_option = m_getopt_table[option_idx].val; 2607 2608 switch (short_option) 2609 { 2610 case 'l': 2611 if (option_arg) 2612 { 2613 m_language = Language::GetLanguageTypeFromString(option_arg); 2614 if (m_language == lldb::eLanguageTypeUnknown) 2615 error.SetErrorStringWithFormat ("unrecognized language '%s'", option_arg); 2616 } 2617 break; 2618 default: 2619 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2620 break; 2621 } 2622 2623 return error; 2624 } 2625 2626 void 2627 OptionParsingStarting () override 2628 { 2629 m_language = lldb::eLanguageTypeUnknown; 2630 } 2631 2632 const OptionDefinition* 2633 GetDefinitions () override 2634 { 2635 return g_option_table; 2636 } 2637 2638 // Options table: Required for subclasses of Options. 2639 2640 static OptionDefinition g_option_table[]; 2641 2642 // Instance variables to hold the values for command options. 2643 2644 lldb::LanguageType m_language; 2645 2646 }; 2647 2648 CommandOptions m_options; 2649 2650 Options * 2651 GetOptions () override 2652 { 2653 return &m_options; 2654 } 2655 2656 public: 2657 CommandObjectTypeCategoryEnable (CommandInterpreter &interpreter) : 2658 CommandObjectParsed (interpreter, 2659 "type category enable", 2660 "Enable a category as a source of formatters.", 2661 NULL), 2662 m_options(interpreter) 2663 { 2664 CommandArgumentEntry type_arg; 2665 CommandArgumentData type_style_arg; 2666 2667 type_style_arg.arg_type = eArgTypeName; 2668 type_style_arg.arg_repetition = eArgRepeatPlus; 2669 2670 type_arg.push_back (type_style_arg); 2671 2672 m_arguments.push_back (type_arg); 2673 2674 } 2675 2676 ~CommandObjectTypeCategoryEnable () override 2677 { 2678 } 2679 2680 protected: 2681 bool 2682 DoExecute (Args& command, CommandReturnObject &result) override 2683 { 2684 const size_t argc = command.GetArgumentCount(); 2685 2686 if (argc < 1 && 2687 m_options.m_language == lldb::eLanguageTypeUnknown) 2688 { 2689 result.AppendErrorWithFormat ("%s takes arguments and/or a language", m_cmd_name.c_str()); 2690 result.SetStatus(eReturnStatusFailed); 2691 return false; 2692 } 2693 2694 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0) 2695 { 2696 DataVisualization::Categories::EnableStar(); 2697 } 2698 else if (argc > 0) 2699 { 2700 for (int i = argc - 1; i >= 0; i--) 2701 { 2702 const char* typeA = command.GetArgumentAtIndex(i); 2703 ConstString typeCS(typeA); 2704 2705 if (!typeCS) 2706 { 2707 result.AppendError("empty category name not allowed"); 2708 result.SetStatus(eReturnStatusFailed); 2709 return false; 2710 } 2711 DataVisualization::Categories::Enable(typeCS); 2712 lldb::TypeCategoryImplSP cate; 2713 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate.get()) 2714 { 2715 if (cate->GetCount() == 0) 2716 { 2717 result.AppendWarning("empty category enabled (typo?)"); 2718 } 2719 } 2720 } 2721 } 2722 2723 if (m_options.m_language != lldb::eLanguageTypeUnknown) 2724 DataVisualization::Categories::Enable(m_options.m_language); 2725 2726 result.SetStatus(eReturnStatusSuccessFinishResult); 2727 return result.Succeeded(); 2728 } 2729 2730 }; 2731 2732 OptionDefinition 2733 CommandObjectTypeCategoryEnable::CommandOptions::g_option_table[] = 2734 { 2735 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Enable the category for this language."}, 2736 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 2737 }; 2738 2739 //------------------------------------------------------------------------- 2740 // CommandObjectTypeCategoryDelete 2741 //------------------------------------------------------------------------- 2742 2743 class CommandObjectTypeCategoryDelete : public CommandObjectParsed 2744 { 2745 public: 2746 CommandObjectTypeCategoryDelete (CommandInterpreter &interpreter) : 2747 CommandObjectParsed (interpreter, 2748 "type category delete", 2749 "Delete a category and all associated formatters.", 2750 NULL) 2751 { 2752 CommandArgumentEntry type_arg; 2753 CommandArgumentData type_style_arg; 2754 2755 type_style_arg.arg_type = eArgTypeName; 2756 type_style_arg.arg_repetition = eArgRepeatPlus; 2757 2758 type_arg.push_back (type_style_arg); 2759 2760 m_arguments.push_back (type_arg); 2761 2762 } 2763 2764 ~CommandObjectTypeCategoryDelete () override 2765 { 2766 } 2767 2768 protected: 2769 bool 2770 DoExecute (Args& command, CommandReturnObject &result) override 2771 { 2772 const size_t argc = command.GetArgumentCount(); 2773 2774 if (argc < 1) 2775 { 2776 result.AppendErrorWithFormat ("%s takes 1 or more arg.\n", m_cmd_name.c_str()); 2777 result.SetStatus(eReturnStatusFailed); 2778 return false; 2779 } 2780 2781 bool success = true; 2782 2783 // the order is not relevant here 2784 for (int i = argc - 1; i >= 0; i--) 2785 { 2786 const char* typeA = command.GetArgumentAtIndex(i); 2787 ConstString typeCS(typeA); 2788 2789 if (!typeCS) 2790 { 2791 result.AppendError("empty category name not allowed"); 2792 result.SetStatus(eReturnStatusFailed); 2793 return false; 2794 } 2795 if (!DataVisualization::Categories::Delete(typeCS)) 2796 success = false; // keep deleting even if we hit an error 2797 } 2798 if (success) 2799 { 2800 result.SetStatus(eReturnStatusSuccessFinishResult); 2801 return result.Succeeded(); 2802 } 2803 else 2804 { 2805 result.AppendError("cannot delete one or more categories\n"); 2806 result.SetStatus(eReturnStatusFailed); 2807 return false; 2808 } 2809 } 2810 }; 2811 2812 //------------------------------------------------------------------------- 2813 // CommandObjectTypeCategoryDisable 2814 //------------------------------------------------------------------------- 2815 2816 class CommandObjectTypeCategoryDisable : public CommandObjectParsed 2817 { 2818 class CommandOptions : public Options 2819 { 2820 public: 2821 2822 CommandOptions (CommandInterpreter &interpreter) : 2823 Options (interpreter) 2824 { 2825 } 2826 2827 ~CommandOptions () override {} 2828 2829 Error 2830 SetOptionValue (uint32_t option_idx, const char *option_arg) override 2831 { 2832 Error error; 2833 const int short_option = m_getopt_table[option_idx].val; 2834 2835 switch (short_option) 2836 { 2837 case 'l': 2838 if (option_arg) 2839 { 2840 m_language = Language::GetLanguageTypeFromString(option_arg); 2841 if (m_language == lldb::eLanguageTypeUnknown) 2842 error.SetErrorStringWithFormat ("unrecognized language '%s'", option_arg); 2843 } 2844 break; 2845 default: 2846 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2847 break; 2848 } 2849 2850 return error; 2851 } 2852 2853 void 2854 OptionParsingStarting () override 2855 { 2856 m_language = lldb::eLanguageTypeUnknown; 2857 } 2858 2859 const OptionDefinition* 2860 GetDefinitions () override 2861 { 2862 return g_option_table; 2863 } 2864 2865 // Options table: Required for subclasses of Options. 2866 2867 static OptionDefinition g_option_table[]; 2868 2869 // Instance variables to hold the values for command options. 2870 2871 lldb::LanguageType m_language; 2872 2873 }; 2874 2875 CommandOptions m_options; 2876 2877 Options * 2878 GetOptions () override 2879 { 2880 return &m_options; 2881 } 2882 2883 public: 2884 CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) : 2885 CommandObjectParsed (interpreter, 2886 "type category disable", 2887 "Disable a category as a source of formatters.", 2888 NULL), 2889 m_options(interpreter) 2890 { 2891 CommandArgumentEntry type_arg; 2892 CommandArgumentData type_style_arg; 2893 2894 type_style_arg.arg_type = eArgTypeName; 2895 type_style_arg.arg_repetition = eArgRepeatPlus; 2896 2897 type_arg.push_back (type_style_arg); 2898 2899 m_arguments.push_back (type_arg); 2900 2901 } 2902 2903 ~CommandObjectTypeCategoryDisable () override 2904 { 2905 } 2906 2907 protected: 2908 bool 2909 DoExecute (Args& command, CommandReturnObject &result) override 2910 { 2911 const size_t argc = command.GetArgumentCount(); 2912 2913 if (argc < 1 && 2914 m_options.m_language == lldb::eLanguageTypeUnknown) 2915 { 2916 result.AppendErrorWithFormat ("%s takes arguments and/or a language", m_cmd_name.c_str()); 2917 result.SetStatus(eReturnStatusFailed); 2918 return false; 2919 } 2920 2921 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0) 2922 { 2923 DataVisualization::Categories::DisableStar(); 2924 } 2925 else if (argc > 0) 2926 { 2927 // the order is not relevant here 2928 for (int i = argc - 1; i >= 0; i--) 2929 { 2930 const char* typeA = command.GetArgumentAtIndex(i); 2931 ConstString typeCS(typeA); 2932 2933 if (!typeCS) 2934 { 2935 result.AppendError("empty category name not allowed"); 2936 result.SetStatus(eReturnStatusFailed); 2937 return false; 2938 } 2939 DataVisualization::Categories::Disable(typeCS); 2940 } 2941 } 2942 2943 if (m_options.m_language != lldb::eLanguageTypeUnknown) 2944 DataVisualization::Categories::Disable(m_options.m_language); 2945 2946 result.SetStatus(eReturnStatusSuccessFinishResult); 2947 return result.Succeeded(); 2948 } 2949 2950 }; 2951 2952 OptionDefinition 2953 CommandObjectTypeCategoryDisable::CommandOptions::g_option_table[] = 2954 { 2955 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Enable the category for this language."}, 2956 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 2957 }; 2958 2959 //------------------------------------------------------------------------- 2960 // CommandObjectTypeCategoryList 2961 //------------------------------------------------------------------------- 2962 2963 class CommandObjectTypeCategoryList : public CommandObjectParsed 2964 { 2965 private: 2966 2967 struct CommandObjectTypeCategoryList_CallbackParam 2968 { 2969 CommandReturnObject* result; 2970 RegularExpression* regex; 2971 2972 CommandObjectTypeCategoryList_CallbackParam(CommandReturnObject* res, 2973 RegularExpression* rex = NULL) : 2974 result(res), 2975 regex(rex) 2976 { 2977 } 2978 2979 }; 2980 2981 static bool 2982 PerCategoryCallback(void* param_vp, 2983 const lldb::TypeCategoryImplSP& cate) 2984 { 2985 CommandObjectTypeCategoryList_CallbackParam* param = 2986 (CommandObjectTypeCategoryList_CallbackParam*)param_vp; 2987 CommandReturnObject* result = param->result; 2988 RegularExpression* regex = param->regex; 2989 2990 const char* cate_name = cate->GetName(); 2991 2992 if (regex == NULL || strcmp(cate_name, regex->GetText()) == 0 || regex->Execute(cate_name)) 2993 result->GetOutputStream().Printf("Category: %s\n", cate->GetDescription().c_str()); 2994 return true; 2995 } 2996 public: 2997 CommandObjectTypeCategoryList (CommandInterpreter &interpreter) : 2998 CommandObjectParsed (interpreter, 2999 "type category list", 3000 "Provide a list of all existing categories.", 3001 NULL) 3002 { 3003 CommandArgumentEntry type_arg; 3004 CommandArgumentData type_style_arg; 3005 3006 type_style_arg.arg_type = eArgTypeName; 3007 type_style_arg.arg_repetition = eArgRepeatOptional; 3008 3009 type_arg.push_back (type_style_arg); 3010 3011 m_arguments.push_back (type_arg); 3012 } 3013 3014 ~CommandObjectTypeCategoryList () override 3015 { 3016 } 3017 3018 protected: 3019 bool 3020 DoExecute (Args& command, CommandReturnObject &result) override 3021 { 3022 const size_t argc = command.GetArgumentCount(); 3023 RegularExpression* regex = NULL; 3024 3025 if (argc == 0) 3026 ; 3027 else if (argc == 1) 3028 regex = new RegularExpression(command.GetArgumentAtIndex(0)); 3029 else 3030 { 3031 result.AppendErrorWithFormat ("%s takes 0 or one arg.\n", m_cmd_name.c_str()); 3032 result.SetStatus(eReturnStatusFailed); 3033 return false; 3034 } 3035 3036 CommandObjectTypeCategoryList_CallbackParam param(&result, 3037 regex); 3038 3039 DataVisualization::Categories::LoopThrough(PerCategoryCallback, ¶m); 3040 3041 if (regex) 3042 delete regex; 3043 3044 result.SetStatus(eReturnStatusSuccessFinishResult); 3045 return result.Succeeded(); 3046 } 3047 3048 }; 3049 3050 //------------------------------------------------------------------------- 3051 // CommandObjectTypeFilterList 3052 //------------------------------------------------------------------------- 3053 3054 bool CommandObjectTypeFilterList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry); 3055 bool CommandObjectTypeFilterRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry); 3056 3057 class CommandObjectTypeFilterList; 3058 3059 struct CommandObjectTypeFilterList_LoopCallbackParam { 3060 CommandObjectTypeFilterList* self; 3061 CommandReturnObject* result; 3062 RegularExpression* regex; 3063 RegularExpression* cate_regex; 3064 CommandObjectTypeFilterList_LoopCallbackParam(CommandObjectTypeFilterList* S, CommandReturnObject* R, 3065 RegularExpression* X = NULL, 3066 RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {} 3067 }; 3068 3069 class CommandObjectTypeFilterList : public CommandObjectParsed 3070 { 3071 3072 class CommandOptions : public Options 3073 { 3074 public: 3075 3076 CommandOptions (CommandInterpreter &interpreter) : 3077 Options (interpreter) 3078 { 3079 } 3080 3081 ~CommandOptions () override {} 3082 3083 Error 3084 SetOptionValue (uint32_t option_idx, const char *option_arg) override 3085 { 3086 Error error; 3087 const int short_option = m_getopt_table[option_idx].val; 3088 3089 switch (short_option) 3090 { 3091 case 'w': 3092 m_category_regex = std::string(option_arg); 3093 break; 3094 default: 3095 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 3096 break; 3097 } 3098 3099 return error; 3100 } 3101 3102 void 3103 OptionParsingStarting () override 3104 { 3105 m_category_regex = ""; 3106 } 3107 3108 const OptionDefinition* 3109 GetDefinitions () override 3110 { 3111 return g_option_table; 3112 } 3113 3114 // Options table: Required for subclasses of Options. 3115 3116 static OptionDefinition g_option_table[]; 3117 3118 // Instance variables to hold the values for command options. 3119 3120 std::string m_category_regex; 3121 3122 }; 3123 3124 CommandOptions m_options; 3125 3126 Options * 3127 GetOptions () override 3128 { 3129 return &m_options; 3130 } 3131 3132 public: 3133 CommandObjectTypeFilterList (CommandInterpreter &interpreter) : 3134 CommandObjectParsed (interpreter, 3135 "type filter list", 3136 "Show a list of current filters.", 3137 NULL), 3138 m_options(interpreter) 3139 { 3140 CommandArgumentEntry type_arg; 3141 CommandArgumentData type_style_arg; 3142 3143 type_style_arg.arg_type = eArgTypeName; 3144 type_style_arg.arg_repetition = eArgRepeatOptional; 3145 3146 type_arg.push_back (type_style_arg); 3147 3148 m_arguments.push_back (type_arg); 3149 } 3150 3151 ~CommandObjectTypeFilterList () override 3152 { 3153 } 3154 3155 protected: 3156 bool 3157 DoExecute (Args& command, CommandReturnObject &result) override 3158 { 3159 const size_t argc = command.GetArgumentCount(); 3160 3161 CommandObjectTypeFilterList_LoopCallbackParam *param; 3162 RegularExpression* cate_regex = 3163 m_options.m_category_regex.empty() ? NULL : 3164 new RegularExpression(m_options.m_category_regex.c_str()); 3165 3166 if (argc == 1) 3167 { 3168 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 3169 regex->Compile(command.GetArgumentAtIndex(0)); 3170 param = new CommandObjectTypeFilterList_LoopCallbackParam(this,&result,regex,cate_regex); 3171 } 3172 else 3173 param = new CommandObjectTypeFilterList_LoopCallbackParam(this,&result,NULL,cate_regex); 3174 3175 DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); 3176 delete param; 3177 3178 if (cate_regex) 3179 delete cate_regex; 3180 3181 result.SetStatus(eReturnStatusSuccessFinishResult); 3182 return result.Succeeded(); 3183 } 3184 3185 private: 3186 3187 static bool 3188 PerCategoryCallback(void* param_vp, 3189 const lldb::TypeCategoryImplSP& cate) 3190 { 3191 3192 const char* cate_name = cate->GetName(); 3193 3194 CommandObjectTypeFilterList_LoopCallbackParam* param = 3195 (CommandObjectTypeFilterList_LoopCallbackParam*)param_vp; 3196 CommandReturnObject* result = param->result; 3197 3198 // if the category is disabled or empty and there is no regex, just skip it 3199 if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter) == 0) && param->cate_regex == NULL) 3200 return true; 3201 3202 // if we have a regex and this category does not match it, just skip it 3203 if(param->cate_regex != NULL && strcmp(cate_name,param->cate_regex->GetText()) != 0 && param->cate_regex->Execute(cate_name) == false) 3204 return true; 3205 3206 result->GetOutputStream().Printf("-----------------------\nCategory: %s\n-----------------------\n", cate->GetDescription().c_str()); 3207 3208 cate->GetTypeFiltersContainer()->LoopThrough(CommandObjectTypeFilterList_LoopCallback, param_vp); 3209 3210 if (cate->GetRegexTypeFiltersContainer()->GetCount() > 0) 3211 { 3212 result->GetOutputStream().Printf("Regex-based filters (slower):\n"); 3213 cate->GetRegexTypeFiltersContainer()->LoopThrough(CommandObjectTypeFilterRXList_LoopCallback, param_vp); 3214 } 3215 3216 return true; 3217 } 3218 3219 bool 3220 LoopCallback (const char* type, 3221 const SyntheticChildren::SharedPointer& entry, 3222 RegularExpression* regex, 3223 CommandReturnObject *result) 3224 { 3225 if (regex == NULL || regex->Execute(type)) 3226 result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); 3227 return true; 3228 } 3229 3230 friend bool CommandObjectTypeFilterList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry); 3231 friend bool CommandObjectTypeFilterRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry); 3232 }; 3233 3234 bool 3235 CommandObjectTypeFilterList_LoopCallback (void* pt2self, 3236 ConstString type, 3237 const SyntheticChildren::SharedPointer& entry) 3238 { 3239 CommandObjectTypeFilterList_LoopCallbackParam* param = (CommandObjectTypeFilterList_LoopCallbackParam*)pt2self; 3240 return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result); 3241 } 3242 3243 bool 3244 CommandObjectTypeFilterRXList_LoopCallback (void* pt2self, 3245 lldb::RegularExpressionSP regex, 3246 const SyntheticChildren::SharedPointer& entry) 3247 { 3248 CommandObjectTypeFilterList_LoopCallbackParam* param = (CommandObjectTypeFilterList_LoopCallbackParam*)pt2self; 3249 return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); 3250 } 3251 3252 3253 OptionDefinition 3254 CommandObjectTypeFilterList::CommandOptions::g_option_table[] = 3255 { 3256 { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."}, 3257 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 3258 }; 3259 3260 #ifndef LLDB_DISABLE_PYTHON 3261 3262 //------------------------------------------------------------------------- 3263 // CommandObjectTypeSynthList 3264 //------------------------------------------------------------------------- 3265 3266 bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry); 3267 bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry); 3268 3269 class CommandObjectTypeSynthList; 3270 3271 struct CommandObjectTypeSynthList_LoopCallbackParam { 3272 CommandObjectTypeSynthList* self; 3273 CommandReturnObject* result; 3274 RegularExpression* regex; 3275 RegularExpression* cate_regex; 3276 CommandObjectTypeSynthList_LoopCallbackParam(CommandObjectTypeSynthList* S, CommandReturnObject* R, 3277 RegularExpression* X = NULL, 3278 RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {} 3279 }; 3280 3281 class CommandObjectTypeSynthList : public CommandObjectParsed 3282 { 3283 3284 class CommandOptions : public Options 3285 { 3286 public: 3287 3288 CommandOptions (CommandInterpreter &interpreter) : 3289 Options (interpreter) 3290 { 3291 } 3292 3293 ~CommandOptions () override {} 3294 3295 Error 3296 SetOptionValue (uint32_t option_idx, const char *option_arg) override 3297 { 3298 Error error; 3299 const int short_option = m_getopt_table[option_idx].val; 3300 3301 switch (short_option) 3302 { 3303 case 'w': 3304 m_category_regex = std::string(option_arg); 3305 break; 3306 default: 3307 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 3308 break; 3309 } 3310 3311 return error; 3312 } 3313 3314 void 3315 OptionParsingStarting () override 3316 { 3317 m_category_regex = ""; 3318 } 3319 3320 const OptionDefinition* 3321 GetDefinitions () override 3322 { 3323 return g_option_table; 3324 } 3325 3326 // Options table: Required for subclasses of Options. 3327 3328 static OptionDefinition g_option_table[]; 3329 3330 // Instance variables to hold the values for command options. 3331 3332 std::string m_category_regex; 3333 3334 }; 3335 3336 CommandOptions m_options; 3337 3338 Options * 3339 GetOptions () override 3340 { 3341 return &m_options; 3342 } 3343 3344 public: 3345 CommandObjectTypeSynthList (CommandInterpreter &interpreter) : 3346 CommandObjectParsed (interpreter, 3347 "type synthetic list", 3348 "Show a list of current synthetic providers.", 3349 NULL), 3350 m_options(interpreter) 3351 { 3352 CommandArgumentEntry type_arg; 3353 CommandArgumentData type_style_arg; 3354 3355 type_style_arg.arg_type = eArgTypeName; 3356 type_style_arg.arg_repetition = eArgRepeatOptional; 3357 3358 type_arg.push_back (type_style_arg); 3359 3360 m_arguments.push_back (type_arg); 3361 } 3362 3363 ~CommandObjectTypeSynthList () override 3364 { 3365 } 3366 3367 protected: 3368 bool 3369 DoExecute (Args& command, CommandReturnObject &result) override 3370 { 3371 const size_t argc = command.GetArgumentCount(); 3372 3373 CommandObjectTypeSynthList_LoopCallbackParam *param; 3374 RegularExpression* cate_regex = 3375 m_options.m_category_regex.empty() ? NULL : 3376 new RegularExpression(m_options.m_category_regex.c_str()); 3377 3378 if (argc == 1) 3379 { 3380 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 3381 regex->Compile(command.GetArgumentAtIndex(0)); 3382 param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,regex,cate_regex); 3383 } 3384 else 3385 param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,NULL,cate_regex); 3386 3387 DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); 3388 delete param; 3389 3390 if (cate_regex) 3391 delete cate_regex; 3392 3393 result.SetStatus(eReturnStatusSuccessFinishResult); 3394 return result.Succeeded(); 3395 } 3396 3397 private: 3398 3399 static bool 3400 PerCategoryCallback(void* param_vp, 3401 const lldb::TypeCategoryImplSP& cate) 3402 { 3403 3404 CommandObjectTypeSynthList_LoopCallbackParam* param = 3405 (CommandObjectTypeSynthList_LoopCallbackParam*)param_vp; 3406 CommandReturnObject* result = param->result; 3407 3408 const char* cate_name = cate->GetName(); 3409 3410 // if the category is disabled or empty and there is no regex, just skip it 3411 if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth) == 0) && param->cate_regex == NULL) 3412 return true; 3413 3414 // if we have a regex and this category does not match it, just skip it 3415 if(param->cate_regex != NULL && strcmp(cate_name,param->cate_regex->GetText()) != 0 && param->cate_regex->Execute(cate_name) == false) 3416 return true; 3417 3418 result->GetOutputStream().Printf("-----------------------\nCategory: %s\n-----------------------\n", cate->GetDescription().c_str()); 3419 3420 cate->GetTypeSyntheticsContainer()->LoopThrough(CommandObjectTypeSynthList_LoopCallback, param_vp); 3421 3422 if (cate->GetRegexTypeSyntheticsContainer()->GetCount() > 0) 3423 { 3424 result->GetOutputStream().Printf("Regex-based synthetic providers (slower):\n"); 3425 cate->GetRegexTypeSyntheticsContainer()->LoopThrough(CommandObjectTypeSynthRXList_LoopCallback, param_vp); 3426 } 3427 3428 return true; 3429 } 3430 3431 bool 3432 LoopCallback (const char* type, 3433 const SyntheticChildren::SharedPointer& entry, 3434 RegularExpression* regex, 3435 CommandReturnObject *result) 3436 { 3437 if (regex == NULL || regex->Execute(type)) 3438 result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); 3439 return true; 3440 } 3441 3442 friend bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry); 3443 friend bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry); 3444 }; 3445 3446 bool 3447 CommandObjectTypeSynthList_LoopCallback (void* pt2self, 3448 ConstString type, 3449 const SyntheticChildren::SharedPointer& entry) 3450 { 3451 CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self; 3452 return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result); 3453 } 3454 3455 bool 3456 CommandObjectTypeSynthRXList_LoopCallback (void* pt2self, 3457 lldb::RegularExpressionSP regex, 3458 const SyntheticChildren::SharedPointer& entry) 3459 { 3460 CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self; 3461 return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); 3462 } 3463 3464 3465 OptionDefinition 3466 CommandObjectTypeSynthList::CommandOptions::g_option_table[] = 3467 { 3468 { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."}, 3469 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 3470 }; 3471 3472 #endif // #ifndef LLDB_DISABLE_PYTHON 3473 //------------------------------------------------------------------------- 3474 // CommandObjectTypeFilterDelete 3475 //------------------------------------------------------------------------- 3476 3477 class CommandObjectTypeFilterDelete : public CommandObjectParsed 3478 { 3479 private: 3480 class CommandOptions : public Options 3481 { 3482 public: 3483 3484 CommandOptions (CommandInterpreter &interpreter) : 3485 Options (interpreter) 3486 { 3487 } 3488 3489 ~CommandOptions () override {} 3490 3491 Error 3492 SetOptionValue (uint32_t option_idx, const char *option_arg) override 3493 { 3494 Error error; 3495 const int short_option = m_getopt_table[option_idx].val; 3496 3497 switch (short_option) 3498 { 3499 case 'a': 3500 m_delete_all = true; 3501 break; 3502 case 'w': 3503 m_category = std::string(option_arg); 3504 break; 3505 default: 3506 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 3507 break; 3508 } 3509 3510 return error; 3511 } 3512 3513 void 3514 OptionParsingStarting () override 3515 { 3516 m_delete_all = false; 3517 m_category = "default"; 3518 } 3519 3520 const OptionDefinition* 3521 GetDefinitions () override 3522 { 3523 return g_option_table; 3524 } 3525 3526 // Options table: Required for subclasses of Options. 3527 3528 static OptionDefinition g_option_table[]; 3529 3530 // Instance variables to hold the values for command options. 3531 3532 bool m_delete_all; 3533 std::string m_category; 3534 3535 }; 3536 3537 CommandOptions m_options; 3538 3539 Options * 3540 GetOptions () override 3541 { 3542 return &m_options; 3543 } 3544 3545 static bool 3546 PerCategoryCallback(void* param, 3547 const lldb::TypeCategoryImplSP& cate) 3548 { 3549 ConstString *name = (ConstString*)param; 3550 return cate->Delete(*name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter); 3551 } 3552 3553 public: 3554 CommandObjectTypeFilterDelete (CommandInterpreter &interpreter) : 3555 CommandObjectParsed (interpreter, 3556 "type filter delete", 3557 "Delete an existing filter for a type.", 3558 NULL), 3559 m_options(interpreter) 3560 { 3561 CommandArgumentEntry type_arg; 3562 CommandArgumentData type_style_arg; 3563 3564 type_style_arg.arg_type = eArgTypeName; 3565 type_style_arg.arg_repetition = eArgRepeatPlain; 3566 3567 type_arg.push_back (type_style_arg); 3568 3569 m_arguments.push_back (type_arg); 3570 3571 } 3572 3573 ~CommandObjectTypeFilterDelete () override 3574 { 3575 } 3576 3577 protected: 3578 bool 3579 DoExecute (Args& command, CommandReturnObject &result) override 3580 { 3581 const size_t argc = command.GetArgumentCount(); 3582 3583 if (argc != 1) 3584 { 3585 result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); 3586 result.SetStatus(eReturnStatusFailed); 3587 return false; 3588 } 3589 3590 const char* typeA = command.GetArgumentAtIndex(0); 3591 ConstString typeCS(typeA); 3592 3593 if (!typeCS) 3594 { 3595 result.AppendError("empty typenames not allowed"); 3596 result.SetStatus(eReturnStatusFailed); 3597 return false; 3598 } 3599 3600 if (m_options.m_delete_all) 3601 { 3602 DataVisualization::Categories::LoopThrough(PerCategoryCallback, (void*)&typeCS); 3603 result.SetStatus(eReturnStatusSuccessFinishNoResult); 3604 return result.Succeeded(); 3605 } 3606 3607 lldb::TypeCategoryImplSP category; 3608 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 3609 3610 bool delete_category = category->GetTypeFiltersContainer()->Delete(typeCS); 3611 delete_category = category->GetRegexTypeFiltersContainer()->Delete(typeCS) || delete_category; 3612 3613 if (delete_category) 3614 { 3615 result.SetStatus(eReturnStatusSuccessFinishNoResult); 3616 return result.Succeeded(); 3617 } 3618 else 3619 { 3620 result.AppendErrorWithFormat ("no custom synthetic provider for %s.\n", typeA); 3621 result.SetStatus(eReturnStatusFailed); 3622 return false; 3623 } 3624 3625 } 3626 }; 3627 3628 OptionDefinition 3629 CommandObjectTypeFilterDelete::CommandOptions::g_option_table[] = 3630 { 3631 { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Delete from every category."}, 3632 { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Delete from given category."}, 3633 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 3634 }; 3635 3636 #ifndef LLDB_DISABLE_PYTHON 3637 3638 //------------------------------------------------------------------------- 3639 // CommandObjectTypeSynthDelete 3640 //------------------------------------------------------------------------- 3641 3642 class CommandObjectTypeSynthDelete : public CommandObjectParsed 3643 { 3644 private: 3645 class CommandOptions : public Options 3646 { 3647 public: 3648 3649 CommandOptions (CommandInterpreter &interpreter) : 3650 Options (interpreter) 3651 { 3652 } 3653 3654 ~CommandOptions () override {} 3655 3656 Error 3657 SetOptionValue (uint32_t option_idx, const char *option_arg) override 3658 { 3659 Error error; 3660 const int short_option = m_getopt_table[option_idx].val; 3661 3662 switch (short_option) 3663 { 3664 case 'a': 3665 m_delete_all = true; 3666 break; 3667 case 'w': 3668 m_category = std::string(option_arg); 3669 break; 3670 default: 3671 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 3672 break; 3673 } 3674 3675 return error; 3676 } 3677 3678 void 3679 OptionParsingStarting () override 3680 { 3681 m_delete_all = false; 3682 m_category = "default"; 3683 } 3684 3685 const OptionDefinition* 3686 GetDefinitions () override 3687 { 3688 return g_option_table; 3689 } 3690 3691 // Options table: Required for subclasses of Options. 3692 3693 static OptionDefinition g_option_table[]; 3694 3695 // Instance variables to hold the values for command options. 3696 3697 bool m_delete_all; 3698 std::string m_category; 3699 3700 }; 3701 3702 CommandOptions m_options; 3703 3704 Options * 3705 GetOptions () override 3706 { 3707 return &m_options; 3708 } 3709 3710 static bool 3711 PerCategoryCallback(void* param, 3712 const lldb::TypeCategoryImplSP& cate) 3713 { 3714 ConstString* name = (ConstString*)param; 3715 return cate->Delete(*name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth); 3716 } 3717 3718 public: 3719 CommandObjectTypeSynthDelete (CommandInterpreter &interpreter) : 3720 CommandObjectParsed (interpreter, 3721 "type synthetic delete", 3722 "Delete an existing synthetic provider for a type.", 3723 NULL), 3724 m_options(interpreter) 3725 { 3726 CommandArgumentEntry type_arg; 3727 CommandArgumentData type_style_arg; 3728 3729 type_style_arg.arg_type = eArgTypeName; 3730 type_style_arg.arg_repetition = eArgRepeatPlain; 3731 3732 type_arg.push_back (type_style_arg); 3733 3734 m_arguments.push_back (type_arg); 3735 3736 } 3737 3738 ~CommandObjectTypeSynthDelete () override 3739 { 3740 } 3741 3742 protected: 3743 bool 3744 DoExecute (Args& command, CommandReturnObject &result) override 3745 { 3746 const size_t argc = command.GetArgumentCount(); 3747 3748 if (argc != 1) 3749 { 3750 result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); 3751 result.SetStatus(eReturnStatusFailed); 3752 return false; 3753 } 3754 3755 const char* typeA = command.GetArgumentAtIndex(0); 3756 ConstString typeCS(typeA); 3757 3758 if (!typeCS) 3759 { 3760 result.AppendError("empty typenames not allowed"); 3761 result.SetStatus(eReturnStatusFailed); 3762 return false; 3763 } 3764 3765 if (m_options.m_delete_all) 3766 { 3767 DataVisualization::Categories::LoopThrough(PerCategoryCallback, (void*)&typeCS); 3768 result.SetStatus(eReturnStatusSuccessFinishNoResult); 3769 return result.Succeeded(); 3770 } 3771 3772 lldb::TypeCategoryImplSP category; 3773 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 3774 3775 bool delete_category = category->GetTypeSyntheticsContainer()->Delete(typeCS); 3776 delete_category = category->GetRegexTypeSyntheticsContainer()->Delete(typeCS) || delete_category; 3777 3778 if (delete_category) 3779 { 3780 result.SetStatus(eReturnStatusSuccessFinishNoResult); 3781 return result.Succeeded(); 3782 } 3783 else 3784 { 3785 result.AppendErrorWithFormat ("no custom synthetic provider for %s.\n", typeA); 3786 result.SetStatus(eReturnStatusFailed); 3787 return false; 3788 } 3789 3790 } 3791 }; 3792 3793 OptionDefinition 3794 CommandObjectTypeSynthDelete::CommandOptions::g_option_table[] = 3795 { 3796 { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Delete from every category."}, 3797 { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Delete from given category."}, 3798 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 3799 }; 3800 3801 #endif // #ifndef LLDB_DISABLE_PYTHON 3802 3803 //------------------------------------------------------------------------- 3804 // CommandObjectTypeFilterClear 3805 //------------------------------------------------------------------------- 3806 3807 class CommandObjectTypeFilterClear : public CommandObjectParsed 3808 { 3809 private: 3810 3811 class CommandOptions : public Options 3812 { 3813 public: 3814 3815 CommandOptions (CommandInterpreter &interpreter) : 3816 Options (interpreter) 3817 { 3818 } 3819 3820 ~CommandOptions () override {} 3821 3822 Error 3823 SetOptionValue (uint32_t option_idx, const char *option_arg) override 3824 { 3825 Error error; 3826 const int short_option = m_getopt_table[option_idx].val; 3827 3828 switch (short_option) 3829 { 3830 case 'a': 3831 m_delete_all = true; 3832 break; 3833 default: 3834 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 3835 break; 3836 } 3837 3838 return error; 3839 } 3840 3841 void 3842 OptionParsingStarting () override 3843 { 3844 m_delete_all = false; 3845 } 3846 3847 const OptionDefinition* 3848 GetDefinitions () override 3849 { 3850 return g_option_table; 3851 } 3852 3853 // Options table: Required for subclasses of Options. 3854 3855 static OptionDefinition g_option_table[]; 3856 3857 // Instance variables to hold the values for command options. 3858 3859 bool m_delete_all; 3860 bool m_delete_named; 3861 }; 3862 3863 CommandOptions m_options; 3864 3865 Options * 3866 GetOptions () override 3867 { 3868 return &m_options; 3869 } 3870 3871 static bool 3872 PerCategoryCallback(void* param, 3873 const lldb::TypeCategoryImplSP& cate) 3874 { 3875 cate->Clear(eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter); 3876 return true; 3877 3878 } 3879 3880 public: 3881 CommandObjectTypeFilterClear (CommandInterpreter &interpreter) : 3882 CommandObjectParsed (interpreter, 3883 "type filter clear", 3884 "Delete all existing filters.", 3885 NULL), 3886 m_options(interpreter) 3887 { 3888 } 3889 3890 ~CommandObjectTypeFilterClear () override 3891 { 3892 } 3893 3894 protected: 3895 bool 3896 DoExecute (Args& command, CommandReturnObject &result) override 3897 { 3898 3899 if (m_options.m_delete_all) 3900 DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL); 3901 3902 else 3903 { 3904 lldb::TypeCategoryImplSP category; 3905 if (command.GetArgumentCount() > 0) 3906 { 3907 const char* cat_name = command.GetArgumentAtIndex(0); 3908 ConstString cat_nameCS(cat_name); 3909 DataVisualization::Categories::GetCategory(cat_nameCS, category); 3910 } 3911 else 3912 DataVisualization::Categories::GetCategory(ConstString(NULL), category); 3913 category->GetTypeFiltersContainer()->Clear(); 3914 category->GetRegexTypeFiltersContainer()->Clear(); 3915 } 3916 3917 result.SetStatus(eReturnStatusSuccessFinishResult); 3918 return result.Succeeded(); 3919 } 3920 3921 }; 3922 3923 OptionDefinition 3924 CommandObjectTypeFilterClear::CommandOptions::g_option_table[] = 3925 { 3926 { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Clear every category."}, 3927 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 3928 }; 3929 3930 #ifndef LLDB_DISABLE_PYTHON 3931 //------------------------------------------------------------------------- 3932 // CommandObjectTypeSynthClear 3933 //------------------------------------------------------------------------- 3934 3935 class CommandObjectTypeSynthClear : public CommandObjectParsed 3936 { 3937 private: 3938 3939 class CommandOptions : public Options 3940 { 3941 public: 3942 3943 CommandOptions (CommandInterpreter &interpreter) : 3944 Options (interpreter) 3945 { 3946 } 3947 3948 ~CommandOptions () override {} 3949 3950 Error 3951 SetOptionValue (uint32_t option_idx, const char *option_arg) override 3952 { 3953 Error error; 3954 const int short_option = m_getopt_table[option_idx].val; 3955 3956 switch (short_option) 3957 { 3958 case 'a': 3959 m_delete_all = true; 3960 break; 3961 default: 3962 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 3963 break; 3964 } 3965 3966 return error; 3967 } 3968 3969 void 3970 OptionParsingStarting () override 3971 { 3972 m_delete_all = false; 3973 } 3974 3975 const OptionDefinition* 3976 GetDefinitions () override 3977 { 3978 return g_option_table; 3979 } 3980 3981 // Options table: Required for subclasses of Options. 3982 3983 static OptionDefinition g_option_table[]; 3984 3985 // Instance variables to hold the values for command options. 3986 3987 bool m_delete_all; 3988 bool m_delete_named; 3989 }; 3990 3991 CommandOptions m_options; 3992 3993 Options * 3994 GetOptions () override 3995 { 3996 return &m_options; 3997 } 3998 3999 static bool 4000 PerCategoryCallback(void* param, 4001 const lldb::TypeCategoryImplSP& cate) 4002 { 4003 cate->Clear(eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth); 4004 return true; 4005 4006 } 4007 4008 public: 4009 CommandObjectTypeSynthClear (CommandInterpreter &interpreter) : 4010 CommandObjectParsed (interpreter, 4011 "type synthetic clear", 4012 "Delete all existing synthetic providers.", 4013 NULL), 4014 m_options(interpreter) 4015 { 4016 } 4017 4018 ~CommandObjectTypeSynthClear () override 4019 { 4020 } 4021 4022 protected: 4023 bool 4024 DoExecute (Args& command, CommandReturnObject &result) override 4025 { 4026 4027 if (m_options.m_delete_all) 4028 DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL); 4029 4030 else 4031 { 4032 lldb::TypeCategoryImplSP category; 4033 if (command.GetArgumentCount() > 0) 4034 { 4035 const char* cat_name = command.GetArgumentAtIndex(0); 4036 ConstString cat_nameCS(cat_name); 4037 DataVisualization::Categories::GetCategory(cat_nameCS, category); 4038 } 4039 else 4040 DataVisualization::Categories::GetCategory(ConstString(NULL), category); 4041 category->GetTypeSyntheticsContainer()->Clear(); 4042 category->GetRegexTypeSyntheticsContainer()->Clear(); 4043 } 4044 4045 result.SetStatus(eReturnStatusSuccessFinishResult); 4046 return result.Succeeded(); 4047 } 4048 4049 }; 4050 4051 OptionDefinition 4052 CommandObjectTypeSynthClear::CommandOptions::g_option_table[] = 4053 { 4054 { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Clear every category."}, 4055 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 4056 }; 4057 4058 4059 bool 4060 CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result) 4061 { 4062 SynthAddOptions *options = new SynthAddOptions ( m_options.m_skip_pointers, 4063 m_options.m_skip_references, 4064 m_options.m_cascade, 4065 m_options.m_regex, 4066 m_options.m_category); 4067 4068 const size_t argc = command.GetArgumentCount(); 4069 4070 for (size_t i = 0; i < argc; i++) 4071 { 4072 const char* typeA = command.GetArgumentAtIndex(i); 4073 if (typeA && *typeA) 4074 options->m_target_types << typeA; 4075 else 4076 { 4077 result.AppendError("empty typenames not allowed"); 4078 result.SetStatus(eReturnStatusFailed); 4079 return false; 4080 } 4081 } 4082 4083 m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt 4084 *this, // IOHandlerDelegate 4085 true, // Run IOHandler in async mode 4086 options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions 4087 result.SetStatus(eReturnStatusSuccessFinishNoResult); 4088 return result.Succeeded(); 4089 } 4090 4091 bool 4092 CommandObjectTypeSynthAdd::Execute_PythonClass (Args& command, CommandReturnObject &result) 4093 { 4094 const size_t argc = command.GetArgumentCount(); 4095 4096 if (argc < 1) 4097 { 4098 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 4099 result.SetStatus(eReturnStatusFailed); 4100 return false; 4101 } 4102 4103 if (m_options.m_class_name.empty() && !m_options.m_input_python) 4104 { 4105 result.AppendErrorWithFormat ("%s needs either a Python class name or -P to directly input Python code.\n", m_cmd_name.c_str()); 4106 result.SetStatus(eReturnStatusFailed); 4107 return false; 4108 } 4109 4110 SyntheticChildrenSP entry; 4111 4112 ScriptedSyntheticChildren* impl = new ScriptedSyntheticChildren(SyntheticChildren::Flags(). 4113 SetCascades(m_options.m_cascade). 4114 SetSkipPointers(m_options.m_skip_pointers). 4115 SetSkipReferences(m_options.m_skip_references), 4116 m_options.m_class_name.c_str()); 4117 4118 entry.reset(impl); 4119 4120 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 4121 4122 if (interpreter && interpreter->CheckObjectExists(impl->GetPythonClassName()) == false) 4123 result.AppendWarning("The provided class does not exist - please define it before attempting to use this synthetic provider"); 4124 4125 // now I have a valid provider, let's add it to every type 4126 4127 lldb::TypeCategoryImplSP category; 4128 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 4129 4130 Error error; 4131 4132 for (size_t i = 0; i < argc; i++) 4133 { 4134 const char* typeA = command.GetArgumentAtIndex(i); 4135 ConstString typeCS(typeA); 4136 if (typeCS) 4137 { 4138 if (!AddSynth(typeCS, 4139 entry, 4140 m_options.m_regex ? eRegexSynth : eRegularSynth, 4141 m_options.m_category, 4142 &error)) 4143 { 4144 result.AppendError(error.AsCString()); 4145 result.SetStatus(eReturnStatusFailed); 4146 return false; 4147 } 4148 } 4149 else 4150 { 4151 result.AppendError("empty typenames not allowed"); 4152 result.SetStatus(eReturnStatusFailed); 4153 return false; 4154 } 4155 } 4156 4157 result.SetStatus(eReturnStatusSuccessFinishNoResult); 4158 return result.Succeeded(); 4159 } 4160 4161 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) : 4162 CommandObjectParsed (interpreter, 4163 "type synthetic add", 4164 "Add a new synthetic provider for a type.", 4165 NULL), 4166 IOHandlerDelegateMultiline ("DONE"), 4167 m_options (interpreter) 4168 { 4169 CommandArgumentEntry type_arg; 4170 CommandArgumentData type_style_arg; 4171 4172 type_style_arg.arg_type = eArgTypeName; 4173 type_style_arg.arg_repetition = eArgRepeatPlus; 4174 4175 type_arg.push_back (type_style_arg); 4176 4177 m_arguments.push_back (type_arg); 4178 4179 } 4180 4181 bool 4182 CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, 4183 SyntheticChildrenSP entry, 4184 SynthFormatType type, 4185 std::string category_name, 4186 Error* error) 4187 { 4188 lldb::TypeCategoryImplSP category; 4189 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); 4190 4191 if (type == eRegularSynth) 4192 { 4193 if (FixArrayTypeNameWithRegex (type_name)) 4194 type = eRegexSynth; 4195 } 4196 4197 if (category->AnyMatches(type_name, 4198 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 4199 false)) 4200 { 4201 if (error) 4202 error->SetErrorStringWithFormat("cannot add synthetic for type %s when filter is defined in same category!", type_name.AsCString()); 4203 return false; 4204 } 4205 4206 if (type == eRegexSynth) 4207 { 4208 RegularExpressionSP typeRX(new RegularExpression()); 4209 if (!typeRX->Compile(type_name.GetCString())) 4210 { 4211 if (error) 4212 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 4213 return false; 4214 } 4215 4216 category->GetRegexTypeSyntheticsContainer()->Delete(type_name); 4217 category->GetRegexTypeSyntheticsContainer()->Add(typeRX, entry); 4218 4219 return true; 4220 } 4221 else 4222 { 4223 category->GetTypeSyntheticsContainer()->Add(type_name, entry); 4224 return true; 4225 } 4226 } 4227 4228 OptionDefinition 4229 CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] = 4230 { 4231 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, 4232 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 4233 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 4234 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 4235 { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children."}, 4236 { 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."}, 4237 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, 4238 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 4239 }; 4240 4241 #endif // #ifndef LLDB_DISABLE_PYTHON 4242 4243 class CommandObjectTypeFilterAdd : public CommandObjectParsed 4244 { 4245 4246 private: 4247 4248 class CommandOptions : public Options 4249 { 4250 typedef std::vector<std::string> option_vector; 4251 public: 4252 4253 CommandOptions (CommandInterpreter &interpreter) : 4254 Options (interpreter) 4255 { 4256 } 4257 4258 ~CommandOptions () override {} 4259 4260 Error 4261 SetOptionValue (uint32_t option_idx, const char *option_arg) override 4262 { 4263 Error error; 4264 const int short_option = m_getopt_table[option_idx].val; 4265 bool success; 4266 4267 switch (short_option) 4268 { 4269 case 'C': 4270 m_cascade = Args::StringToBoolean(option_arg, true, &success); 4271 if (!success) 4272 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg); 4273 break; 4274 case 'c': 4275 m_expr_paths.push_back(option_arg); 4276 has_child_list = true; 4277 break; 4278 case 'p': 4279 m_skip_pointers = true; 4280 break; 4281 case 'r': 4282 m_skip_references = true; 4283 break; 4284 case 'w': 4285 m_category = std::string(option_arg); 4286 break; 4287 case 'x': 4288 m_regex = true; 4289 break; 4290 default: 4291 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 4292 break; 4293 } 4294 4295 return error; 4296 } 4297 4298 void 4299 OptionParsingStarting () override 4300 { 4301 m_cascade = true; 4302 m_skip_pointers = false; 4303 m_skip_references = false; 4304 m_category = "default"; 4305 m_expr_paths.clear(); 4306 has_child_list = false; 4307 m_regex = false; 4308 } 4309 4310 const OptionDefinition* 4311 GetDefinitions () override 4312 { 4313 return g_option_table; 4314 } 4315 4316 // Options table: Required for subclasses of Options. 4317 4318 static OptionDefinition g_option_table[]; 4319 4320 // Instance variables to hold the values for command options. 4321 4322 bool m_cascade; 4323 bool m_skip_references; 4324 bool m_skip_pointers; 4325 bool m_input_python; 4326 option_vector m_expr_paths; 4327 std::string m_category; 4328 4329 bool has_child_list; 4330 4331 bool m_regex; 4332 4333 typedef option_vector::iterator ExpressionPathsIterator; 4334 }; 4335 4336 CommandOptions m_options; 4337 4338 Options * 4339 GetOptions () override 4340 { 4341 return &m_options; 4342 } 4343 4344 enum FilterFormatType 4345 { 4346 eRegularFilter, 4347 eRegexFilter 4348 }; 4349 4350 bool 4351 AddFilter(ConstString type_name, 4352 SyntheticChildrenSP entry, 4353 FilterFormatType type, 4354 std::string category_name, 4355 Error* error) 4356 { 4357 lldb::TypeCategoryImplSP category; 4358 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); 4359 4360 if (type == eRegularFilter) 4361 { 4362 if (FixArrayTypeNameWithRegex (type_name)) 4363 type = eRegexFilter; 4364 } 4365 4366 if (category->AnyMatches(type_name, 4367 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 4368 false)) 4369 { 4370 if (error) 4371 error->SetErrorStringWithFormat("cannot add filter for type %s when synthetic is defined in same category!", type_name.AsCString()); 4372 return false; 4373 } 4374 4375 if (type == eRegexFilter) 4376 { 4377 RegularExpressionSP typeRX(new RegularExpression()); 4378 if (!typeRX->Compile(type_name.GetCString())) 4379 { 4380 if (error) 4381 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 4382 return false; 4383 } 4384 4385 category->GetRegexTypeFiltersContainer()->Delete(type_name); 4386 category->GetRegexTypeFiltersContainer()->Add(typeRX, entry); 4387 4388 return true; 4389 } 4390 else 4391 { 4392 category->GetTypeFiltersContainer()->Add(type_name, entry); 4393 return true; 4394 } 4395 } 4396 4397 4398 public: 4399 4400 CommandObjectTypeFilterAdd (CommandInterpreter &interpreter) : 4401 CommandObjectParsed (interpreter, 4402 "type filter add", 4403 "Add a new filter for a type.", 4404 NULL), 4405 m_options (interpreter) 4406 { 4407 CommandArgumentEntry type_arg; 4408 CommandArgumentData type_style_arg; 4409 4410 type_style_arg.arg_type = eArgTypeName; 4411 type_style_arg.arg_repetition = eArgRepeatPlus; 4412 4413 type_arg.push_back (type_style_arg); 4414 4415 m_arguments.push_back (type_arg); 4416 4417 SetHelpLong( 4418 R"( 4419 The following examples of 'type filter add' refer to this code snippet for context: 4420 4421 class Foo { 4422 int a; 4423 int b; 4424 int c; 4425 int d; 4426 int e; 4427 int f; 4428 int g; 4429 int h; 4430 int i; 4431 } 4432 Foo my_foo; 4433 4434 Adding a simple filter: 4435 4436 (lldb) type filter add --child a --child g Foo 4437 (lldb) frame variable my_foo 4438 4439 )" "Produces output where only a and g are displayed. Other children of my_foo \ 4440 (b, c, d, e, f, h and i) are available by asking for them explicitly:" R"( 4441 4442 (lldb) frame variable my_foo.b my_foo.c my_foo.i 4443 4444 )" "The formatting option --raw on frame variable bypasses the filter, showing \ 4445 all children of my_foo as if no filter was defined:" R"( 4446 4447 (lldb) frame variable my_foo --raw)" 4448 ); 4449 } 4450 4451 ~CommandObjectTypeFilterAdd () override 4452 { 4453 } 4454 4455 protected: 4456 bool 4457 DoExecute (Args& command, CommandReturnObject &result) override 4458 { 4459 const size_t argc = command.GetArgumentCount(); 4460 4461 if (argc < 1) 4462 { 4463 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 4464 result.SetStatus(eReturnStatusFailed); 4465 return false; 4466 } 4467 4468 if (m_options.m_expr_paths.size() == 0) 4469 { 4470 result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str()); 4471 result.SetStatus(eReturnStatusFailed); 4472 return false; 4473 } 4474 4475 SyntheticChildrenSP entry; 4476 4477 TypeFilterImpl* impl = new TypeFilterImpl(SyntheticChildren::Flags().SetCascades(m_options.m_cascade). 4478 SetSkipPointers(m_options.m_skip_pointers). 4479 SetSkipReferences(m_options.m_skip_references)); 4480 4481 entry.reset(impl); 4482 4483 // go through the expression paths 4484 CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end(); 4485 4486 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++) 4487 impl->AddExpressionPath(*begin); 4488 4489 4490 // now I have a valid provider, let's add it to every type 4491 4492 lldb::TypeCategoryImplSP category; 4493 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 4494 4495 Error error; 4496 4497 WarnOnPotentialUnquotedUnsignedType(command, result); 4498 4499 for (size_t i = 0; i < argc; i++) 4500 { 4501 const char* typeA = command.GetArgumentAtIndex(i); 4502 ConstString typeCS(typeA); 4503 if (typeCS) 4504 { 4505 if (!AddFilter(typeCS, 4506 entry, 4507 m_options.m_regex ? eRegexFilter : eRegularFilter, 4508 m_options.m_category, 4509 &error)) 4510 { 4511 result.AppendError(error.AsCString()); 4512 result.SetStatus(eReturnStatusFailed); 4513 return false; 4514 } 4515 } 4516 else 4517 { 4518 result.AppendError("empty typenames not allowed"); 4519 result.SetStatus(eReturnStatusFailed); 4520 return false; 4521 } 4522 } 4523 4524 result.SetStatus(eReturnStatusSuccessFinishNoResult); 4525 return result.Succeeded(); 4526 } 4527 4528 }; 4529 4530 OptionDefinition 4531 CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] = 4532 { 4533 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, 4534 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 4535 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 4536 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 4537 { LLDB_OPT_SET_ALL, false, "child", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view."}, 4538 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, 4539 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 4540 }; 4541 4542 //---------------------------------------------------------------------- 4543 // "type lookup" 4544 //---------------------------------------------------------------------- 4545 class CommandObjectTypeLookup : public CommandObjectRaw 4546 { 4547 protected: 4548 4549 class CommandOptions : public OptionGroup 4550 { 4551 public: 4552 4553 CommandOptions () : 4554 OptionGroup(), 4555 m_show_help(false), 4556 m_language(eLanguageTypeUnknown) 4557 {} 4558 4559 ~CommandOptions () override {} 4560 4561 uint32_t 4562 GetNumDefinitions () override 4563 { 4564 return 3; 4565 } 4566 4567 const OptionDefinition* 4568 GetDefinitions () override 4569 { 4570 return g_option_table; 4571 } 4572 4573 Error 4574 SetOptionValue (CommandInterpreter &interpreter, 4575 uint32_t option_idx, 4576 const char *option_value) override 4577 { 4578 Error error; 4579 4580 const int short_option = g_option_table[option_idx].short_option; 4581 4582 switch (short_option) 4583 { 4584 case 'h': 4585 m_show_help = true; 4586 break; 4587 4588 case 'l': 4589 m_language = Language::GetLanguageTypeFromString(option_value); 4590 break; 4591 4592 default: 4593 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 4594 break; 4595 } 4596 4597 return error; 4598 } 4599 4600 void 4601 OptionParsingStarting (CommandInterpreter &interpreter) override 4602 { 4603 m_show_help = false; 4604 m_language = eLanguageTypeUnknown; 4605 } 4606 4607 // Options table: Required for subclasses of Options. 4608 4609 static OptionDefinition g_option_table[]; 4610 bool m_show_help; 4611 lldb::LanguageType m_language; 4612 }; 4613 4614 OptionGroupOptions m_option_group; 4615 CommandOptions m_command_options; 4616 4617 public: 4618 4619 CommandObjectTypeLookup (CommandInterpreter &interpreter) : 4620 CommandObjectRaw (interpreter, 4621 "type lookup", 4622 "Lookup a type by name in the select target.", 4623 "type lookup <typename>", 4624 eCommandRequiresTarget), 4625 m_option_group(interpreter), 4626 m_command_options() 4627 { 4628 m_option_group.Append(&m_command_options); 4629 m_option_group.Finalize(); 4630 } 4631 4632 ~CommandObjectTypeLookup () override 4633 { 4634 } 4635 4636 Options * 4637 GetOptions () override 4638 { 4639 return &m_option_group; 4640 } 4641 4642 bool 4643 DoExecute (const char *raw_command_line, CommandReturnObject &result) override 4644 { 4645 if (!raw_command_line || !raw_command_line[0]) 4646 { 4647 result.SetError("type lookup cannot be invoked without a type name as argument"); 4648 return false; 4649 } 4650 4651 m_option_group.NotifyOptionParsingStarting(); 4652 4653 const char * name_of_type = NULL; 4654 4655 if (raw_command_line[0] == '-') 4656 { 4657 // We have some options and these options MUST end with --. 4658 const char *end_options = NULL; 4659 const char *s = raw_command_line; 4660 while (s && s[0]) 4661 { 4662 end_options = ::strstr (s, "--"); 4663 if (end_options) 4664 { 4665 end_options += 2; // Get past the "--" 4666 if (::isspace (end_options[0])) 4667 { 4668 name_of_type = end_options; 4669 while (::isspace (*name_of_type)) 4670 ++name_of_type; 4671 break; 4672 } 4673 } 4674 s = end_options; 4675 } 4676 4677 if (end_options) 4678 { 4679 Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line)); 4680 if (!ParseOptions (args, result)) 4681 return false; 4682 4683 Error error (m_option_group.NotifyOptionParsingFinished()); 4684 if (error.Fail()) 4685 { 4686 result.AppendError (error.AsCString()); 4687 result.SetStatus (eReturnStatusFailed); 4688 return false; 4689 } 4690 } 4691 } 4692 if (nullptr == name_of_type) 4693 name_of_type = raw_command_line; 4694 4695 TargetSP target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget()); 4696 const bool fill_all_in = true; 4697 ExecutionContext exe_ctx(target_sp.get(), fill_all_in); 4698 ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope(); 4699 4700 bool any_found = false; 4701 4702 std::vector<Language*> languages; 4703 4704 if (m_command_options.m_language == eLanguageTypeUnknown) 4705 { 4706 // FIXME: hardcoding languages is not good 4707 languages.push_back(Language::FindPlugin(eLanguageTypeObjC)); 4708 languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus)); 4709 } 4710 else 4711 { 4712 languages.push_back(Language::FindPlugin(m_command_options.m_language)); 4713 } 4714 4715 for (Language* language : languages) 4716 { 4717 if (!language) 4718 continue; 4719 4720 if (auto scavenger = language->GetTypeScavenger()) 4721 { 4722 Language::TypeScavenger::ResultSet search_results; 4723 if (scavenger->Find(best_scope, name_of_type, search_results) > 0) 4724 { 4725 for (const auto& search_result : search_results) 4726 { 4727 if (search_result && search_result->IsValid()) 4728 { 4729 any_found = true; 4730 search_result->DumpToStream(result.GetOutputStream(), this->m_command_options.m_show_help); 4731 } 4732 } 4733 } 4734 } 4735 } 4736 4737 result.SetStatus (any_found ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusSuccessFinishNoResult); 4738 return true; 4739 } 4740 4741 }; 4742 4743 OptionDefinition 4744 CommandObjectTypeLookup::CommandOptions::g_option_table[] = 4745 { 4746 { LLDB_OPT_SET_ALL, false, "show-help", 'h', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display available help for types"}, 4747 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Which language's types should the search scope be"}, 4748 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 4749 }; 4750 4751 template <typename FormatterType> 4752 class CommandObjectFormatterInfo : public CommandObjectRaw 4753 { 4754 public: 4755 typedef std::function<typename FormatterType::SharedPointer(ValueObject&)> DiscoveryFunction; 4756 CommandObjectFormatterInfo (CommandInterpreter &interpreter, 4757 const char* formatter_name, 4758 DiscoveryFunction discovery_func) : 4759 CommandObjectRaw(interpreter, 4760 nullptr, 4761 nullptr, 4762 nullptr, 4763 eCommandRequiresFrame), 4764 m_formatter_name(formatter_name ? formatter_name : ""), 4765 m_discovery_function(discovery_func) 4766 { 4767 StreamString name; 4768 name.Printf("type %s info", formatter_name); 4769 SetCommandName(name.GetData()); 4770 StreamString help; 4771 help.Printf("This command evaluates the provided expression and shows which %s is applied to the resulting value (if any).", formatter_name); 4772 SetHelp(help.GetData()); 4773 StreamString syntax; 4774 syntax.Printf("type %s info <expr>", formatter_name); 4775 SetSyntax(syntax.GetData()); 4776 } 4777 4778 ~CommandObjectFormatterInfo () override 4779 { 4780 } 4781 4782 protected: 4783 bool 4784 DoExecute (const char *command, CommandReturnObject &result) override 4785 { 4786 auto target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); 4787 auto frame_sp = target_sp->GetProcessSP()->GetThreadList().GetSelectedThread()->GetSelectedFrame(); 4788 ValueObjectSP result_valobj_sp; 4789 EvaluateExpressionOptions options; 4790 lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(command, frame_sp.get(), result_valobj_sp, options); 4791 if (expr_result == eExpressionCompleted && result_valobj_sp) 4792 { 4793 result_valobj_sp = result_valobj_sp->GetQualifiedRepresentationIfAvailable(target_sp->GetPreferDynamicValue(), target_sp->GetEnableSyntheticValue()); 4794 typename FormatterType::SharedPointer formatter_sp = m_discovery_function(*result_valobj_sp); 4795 if (formatter_sp) 4796 { 4797 std::string description(formatter_sp->GetDescription()); 4798 result.AppendMessageWithFormat("%s applied to (%s) %s is: %s\n", 4799 m_formatter_name.c_str(), 4800 result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"), 4801 command, 4802 description.c_str()); 4803 result.SetStatus(lldb::eReturnStatusSuccessFinishResult); 4804 } 4805 else 4806 { 4807 result.AppendMessageWithFormat("no %s applies to (%s) %s\n", 4808 m_formatter_name.c_str(), 4809 result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"), 4810 command); 4811 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 4812 } 4813 return true; 4814 } 4815 else 4816 { 4817 result.AppendError("failed to evaluate expression"); 4818 result.SetStatus(lldb::eReturnStatusFailed); 4819 return false; 4820 } 4821 } 4822 4823 private: 4824 std::string m_formatter_name; 4825 DiscoveryFunction m_discovery_function; 4826 }; 4827 4828 class CommandObjectTypeFormat : public CommandObjectMultiword 4829 { 4830 public: 4831 CommandObjectTypeFormat (CommandInterpreter &interpreter) : 4832 CommandObjectMultiword (interpreter, 4833 "type format", 4834 "A set of commands for editing variable value display options", 4835 "type format [<sub-command-options>] ") 4836 { 4837 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter))); 4838 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFormatClear (interpreter))); 4839 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter))); 4840 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFormatList (interpreter))); 4841 LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo<TypeFormatImpl>(interpreter, 4842 "format", 4843 [](ValueObject& valobj) -> TypeFormatImpl::SharedPointer { 4844 return valobj.GetValueFormat(); 4845 }))); 4846 } 4847 4848 4849 ~CommandObjectTypeFormat () override 4850 { 4851 } 4852 }; 4853 4854 #ifndef LLDB_DISABLE_PYTHON 4855 4856 class CommandObjectTypeSynth : public CommandObjectMultiword 4857 { 4858 public: 4859 CommandObjectTypeSynth (CommandInterpreter &interpreter) : 4860 CommandObjectMultiword (interpreter, 4861 "type synthetic", 4862 "A set of commands for operating on synthetic type representations", 4863 "type synthetic [<sub-command-options>] ") 4864 { 4865 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSynthAdd (interpreter))); 4866 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSynthClear (interpreter))); 4867 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSynthDelete (interpreter))); 4868 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSynthList (interpreter))); 4869 LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo<SyntheticChildren>(interpreter, 4870 "synthetic", 4871 [](ValueObject& valobj) -> SyntheticChildren::SharedPointer { 4872 return valobj.GetSyntheticChildren(); 4873 }))); 4874 } 4875 4876 4877 ~CommandObjectTypeSynth () override 4878 { 4879 } 4880 }; 4881 4882 #endif // #ifndef LLDB_DISABLE_PYTHON 4883 4884 class CommandObjectTypeFilter : public CommandObjectMultiword 4885 { 4886 public: 4887 CommandObjectTypeFilter (CommandInterpreter &interpreter) : 4888 CommandObjectMultiword (interpreter, 4889 "type filter", 4890 "A set of commands for operating on type filters", 4891 "type synthetic [<sub-command-options>] ") 4892 { 4893 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeFilterAdd (interpreter))); 4894 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFilterClear (interpreter))); 4895 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFilterDelete (interpreter))); 4896 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFilterList (interpreter))); 4897 } 4898 4899 4900 ~CommandObjectTypeFilter () override 4901 { 4902 } 4903 }; 4904 4905 class CommandObjectTypeCategory : public CommandObjectMultiword 4906 { 4907 public: 4908 CommandObjectTypeCategory (CommandInterpreter &interpreter) : 4909 CommandObjectMultiword (interpreter, 4910 "type category", 4911 "A set of commands for operating on categories", 4912 "type category [<sub-command-options>] ") 4913 { 4914 LoadSubCommand ("define", CommandObjectSP (new CommandObjectTypeCategoryDefine (interpreter))); 4915 LoadSubCommand ("enable", CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter))); 4916 LoadSubCommand ("disable", CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter))); 4917 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter))); 4918 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeCategoryList (interpreter))); 4919 } 4920 4921 4922 ~CommandObjectTypeCategory () override 4923 { 4924 } 4925 }; 4926 4927 class CommandObjectTypeSummary : public CommandObjectMultiword 4928 { 4929 public: 4930 CommandObjectTypeSummary (CommandInterpreter &interpreter) : 4931 CommandObjectMultiword (interpreter, 4932 "type summary", 4933 "A set of commands for editing variable summary display options", 4934 "type summary [<sub-command-options>] ") 4935 { 4936 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter))); 4937 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter))); 4938 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter))); 4939 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); 4940 LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo<TypeSummaryImpl>(interpreter, 4941 "summary", 4942 [](ValueObject& valobj) -> TypeSummaryImpl::SharedPointer { 4943 return valobj.GetSummaryFormat(); 4944 }))); 4945 } 4946 4947 4948 ~CommandObjectTypeSummary () override 4949 { 4950 } 4951 }; 4952 4953 //------------------------------------------------------------------------- 4954 // CommandObjectType 4955 //------------------------------------------------------------------------- 4956 4957 CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) : 4958 CommandObjectMultiword (interpreter, 4959 "type", 4960 "A set of commands for operating on the type system", 4961 "type [<sub-command-options>]") 4962 { 4963 LoadSubCommand ("category", CommandObjectSP (new CommandObjectTypeCategory (interpreter))); 4964 LoadSubCommand ("filter", CommandObjectSP (new CommandObjectTypeFilter (interpreter))); 4965 LoadSubCommand ("format", CommandObjectSP (new CommandObjectTypeFormat (interpreter))); 4966 LoadSubCommand ("summary", CommandObjectSP (new CommandObjectTypeSummary (interpreter))); 4967 #ifndef LLDB_DISABLE_PYTHON 4968 LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter))); 4969 #endif 4970 LoadSubCommand ("lookup", CommandObjectSP (new CommandObjectTypeLookup (interpreter))); 4971 } 4972 4973 4974 CommandObjectType::~CommandObjectType () 4975 { 4976 } 4977 4978 4979