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