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