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 void 1314 FormatterSpecificList (CommandReturnObject &result) 1315 { 1316 } 1317 1318 bool 1319 DoExecute (Args& command, CommandReturnObject &result) override 1320 { 1321 const size_t argc = command.GetArgumentCount(); 1322 1323 std::unique_ptr<RegularExpression> category_regex; 1324 std::unique_ptr<RegularExpression> formatter_regex; 1325 1326 if (m_options.m_category_regex.OptionWasSet()) 1327 { 1328 category_regex.reset(new RegularExpression()); 1329 if (!category_regex->Compile(m_options.m_category_regex.GetCurrentValue())) 1330 { 1331 result.AppendErrorWithFormat("syntax error in category regular expression '%s'", m_options.m_category_regex.GetCurrentValue()); 1332 result.SetStatus(eReturnStatusFailed); 1333 return false; 1334 } 1335 } 1336 1337 if (argc == 1) 1338 { 1339 const char* arg = command.GetArgumentAtIndex(0); 1340 formatter_regex.reset(new RegularExpression()); 1341 if (!formatter_regex->Compile(arg)) 1342 { 1343 result.AppendErrorWithFormat("syntax error in regular expression '%s'", arg); 1344 result.SetStatus(eReturnStatusFailed); 1345 return false; 1346 } 1347 } 1348 1349 auto category_closure = [&result, &formatter_regex] (const lldb::TypeCategoryImplSP& category) -> void { 1350 result.GetOutputStream().Printf("-----------------------\nCategory: %s\n-----------------------\n", category->GetName()); 1351 TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach; 1352 foreach.SetExact([&result, &formatter_regex] (ConstString name, const FormatterSharedPointer& format_sp) -> bool { 1353 if (formatter_regex) 1354 { 1355 bool escape = true; 1356 if (0 == strcmp(name.AsCString(), formatter_regex->GetText())) 1357 { 1358 escape = false; 1359 } 1360 else if (formatter_regex->Execute(name.AsCString())) 1361 { 1362 escape = false; 1363 } 1364 1365 if (escape) 1366 return true; 1367 } 1368 1369 result.GetOutputStream().Printf ("%s: %s\n", name.AsCString(), format_sp->GetDescription().c_str()); 1370 1371 return true; 1372 }); 1373 1374 foreach.SetWithRegex( [&result, &formatter_regex] (RegularExpressionSP regex_sp, const FormatterSharedPointer& format_sp) -> bool { 1375 if (formatter_regex) 1376 { 1377 bool escape = true; 1378 if (0 == strcmp(regex_sp->GetText(), formatter_regex->GetText())) 1379 { 1380 escape = false; 1381 } 1382 else if (formatter_regex->Execute(regex_sp->GetText())) 1383 { 1384 escape = false; 1385 } 1386 1387 if (escape) 1388 return true; 1389 } 1390 1391 result.GetOutputStream().Printf ("%s: %s\n", regex_sp->GetText(), format_sp->GetDescription().c_str()); 1392 1393 return true; 1394 }); 1395 1396 category->ForEach(foreach); 1397 }; 1398 1399 if (m_options.m_category_language.OptionWasSet()) 1400 { 1401 lldb::TypeCategoryImplSP category_sp; 1402 DataVisualization::Categories::GetCategory(m_options.m_category_language.GetCurrentValue(), category_sp); 1403 if (category_sp) 1404 category_closure(category_sp); 1405 } 1406 else 1407 { 1408 DataVisualization::Categories::ForEach( [this, &command, &result, &category_regex, &formatter_regex, &category_closure] (const lldb::TypeCategoryImplSP& category) -> bool { 1409 if (category_regex) 1410 { 1411 bool escape = true; 1412 if (0 == strcmp(category->GetName(), category_regex->GetText())) 1413 { 1414 escape = false; 1415 } 1416 else if (category_regex->Execute(category->GetName())) 1417 { 1418 escape = false; 1419 } 1420 1421 if (escape) 1422 return true; 1423 } 1424 1425 category_closure(category); 1426 1427 return true; 1428 }); 1429 1430 FormatterSpecificList(result); 1431 } 1432 1433 result.SetStatus(eReturnStatusSuccessFinishResult); 1434 return result.Succeeded(); 1435 } 1436 }; 1437 1438 //------------------------------------------------------------------------- 1439 // CommandObjectTypeFormatList 1440 //------------------------------------------------------------------------- 1441 1442 class CommandObjectTypeFormatList : public CommandObjectTypeFormatterList<TypeFormatImpl> 1443 { 1444 public: 1445 1446 CommandObjectTypeFormatList (CommandInterpreter &interpreter) : 1447 CommandObjectTypeFormatterList(interpreter, 1448 "type format list", 1449 "Show a list of current formats.") 1450 { 1451 } 1452 }; 1453 1454 #ifndef LLDB_DISABLE_PYTHON 1455 1456 //------------------------------------------------------------------------- 1457 // CommandObjectTypeSummaryAdd 1458 //------------------------------------------------------------------------- 1459 1460 #endif // LLDB_DISABLE_PYTHON 1461 1462 Error 1463 CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) 1464 { 1465 Error error; 1466 const int short_option = m_getopt_table[option_idx].val; 1467 bool success; 1468 1469 switch (short_option) 1470 { 1471 case 'C': 1472 m_flags.SetCascades(Args::StringToBoolean(option_arg, true, &success)); 1473 if (!success) 1474 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg); 1475 break; 1476 case 'e': 1477 m_flags.SetDontShowChildren(false); 1478 break; 1479 case 'h': 1480 m_flags.SetHideEmptyAggregates(true); 1481 break; 1482 case 'v': 1483 m_flags.SetDontShowValue(true); 1484 break; 1485 case 'c': 1486 m_flags.SetShowMembersOneLiner(true); 1487 break; 1488 case 's': 1489 m_format_string = std::string(option_arg); 1490 break; 1491 case 'p': 1492 m_flags.SetSkipPointers(true); 1493 break; 1494 case 'r': 1495 m_flags.SetSkipReferences(true); 1496 break; 1497 case 'x': 1498 m_regex = true; 1499 break; 1500 case 'n': 1501 m_name.SetCString(option_arg); 1502 break; 1503 case 'o': 1504 m_python_script = std::string(option_arg); 1505 m_is_add_script = true; 1506 break; 1507 case 'F': 1508 m_python_function = std::string(option_arg); 1509 m_is_add_script = true; 1510 break; 1511 case 'P': 1512 m_is_add_script = true; 1513 break; 1514 case 'w': 1515 m_category = std::string(option_arg); 1516 break; 1517 case 'O': 1518 m_flags.SetHideItemNames(true); 1519 break; 1520 default: 1521 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1522 break; 1523 } 1524 1525 return error; 1526 } 1527 1528 void 1529 CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting () 1530 { 1531 m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false); 1532 m_flags.SetShowMembersOneLiner(false).SetSkipPointers(false).SetSkipReferences(false).SetHideItemNames(false); 1533 1534 m_regex = false; 1535 m_name.Clear(); 1536 m_python_script = ""; 1537 m_python_function = ""; 1538 m_format_string = ""; 1539 m_is_add_script = false; 1540 m_category = "default"; 1541 } 1542 1543 #ifndef LLDB_DISABLE_PYTHON 1544 1545 bool 1546 CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturnObject &result) 1547 { 1548 const size_t argc = command.GetArgumentCount(); 1549 1550 if (argc < 1 && !m_options.m_name) 1551 { 1552 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 1553 result.SetStatus(eReturnStatusFailed); 1554 return false; 1555 } 1556 1557 TypeSummaryImplSP script_format; 1558 1559 if (!m_options.m_python_function.empty()) // we have a Python function ready to use 1560 { 1561 const char *funct_name = m_options.m_python_function.c_str(); 1562 if (!funct_name || !funct_name[0]) 1563 { 1564 result.AppendError ("function name empty.\n"); 1565 result.SetStatus (eReturnStatusFailed); 1566 return false; 1567 } 1568 1569 std::string code = (" " + m_options.m_python_function + "(valobj,internal_dict)"); 1570 1571 script_format.reset(new ScriptSummaryFormat(m_options.m_flags, 1572 funct_name, 1573 code.c_str())); 1574 1575 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 1576 1577 if (interpreter && !interpreter->CheckObjectExists(funct_name)) 1578 result.AppendWarningWithFormat("The provided function \"%s\" does not exist - " 1579 "please define it before attempting to use this summary.\n", 1580 funct_name); 1581 } 1582 else if (!m_options.m_python_script.empty()) // we have a quick 1-line script, just use it 1583 { 1584 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 1585 if (!interpreter) 1586 { 1587 result.AppendError ("script interpreter missing - unable to generate function wrapper.\n"); 1588 result.SetStatus (eReturnStatusFailed); 1589 return false; 1590 } 1591 StringList funct_sl; 1592 funct_sl << m_options.m_python_script.c_str(); 1593 std::string funct_name_str; 1594 if (!interpreter->GenerateTypeScriptFunction (funct_sl, 1595 funct_name_str)) 1596 { 1597 result.AppendError ("unable to generate function wrapper.\n"); 1598 result.SetStatus (eReturnStatusFailed); 1599 return false; 1600 } 1601 if (funct_name_str.empty()) 1602 { 1603 result.AppendError ("script interpreter failed to generate a valid function name.\n"); 1604 result.SetStatus (eReturnStatusFailed); 1605 return false; 1606 } 1607 1608 std::string code = " " + m_options.m_python_script; 1609 1610 script_format.reset(new ScriptSummaryFormat(m_options.m_flags, 1611 funct_name_str.c_str(), 1612 code.c_str())); 1613 } 1614 else 1615 { 1616 // Use an IOHandler to grab Python code from the user 1617 ScriptAddOptions *options = new ScriptAddOptions(m_options.m_flags, 1618 m_options.m_regex, 1619 m_options.m_name, 1620 m_options.m_category); 1621 1622 for (size_t i = 0; i < argc; i++) 1623 { 1624 const char* typeA = command.GetArgumentAtIndex(i); 1625 if (typeA && *typeA) 1626 options->m_target_types << typeA; 1627 else 1628 { 1629 result.AppendError("empty typenames not allowed"); 1630 result.SetStatus(eReturnStatusFailed); 1631 return false; 1632 } 1633 } 1634 1635 m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt 1636 *this, // IOHandlerDelegate 1637 true, // Run IOHandler in async mode 1638 options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions 1639 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1640 1641 return result.Succeeded(); 1642 } 1643 1644 // if I am here, script_format must point to something good, so I can add that 1645 // as a script summary to all interested parties 1646 1647 Error error; 1648 1649 for (size_t i = 0; i < command.GetArgumentCount(); i++) 1650 { 1651 const char *type_name = command.GetArgumentAtIndex(i); 1652 CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name), 1653 script_format, 1654 (m_options.m_regex ? eRegexSummary : eRegularSummary), 1655 m_options.m_category, 1656 &error); 1657 if (error.Fail()) 1658 { 1659 result.AppendError(error.AsCString()); 1660 result.SetStatus(eReturnStatusFailed); 1661 return false; 1662 } 1663 } 1664 1665 if (m_options.m_name) 1666 { 1667 AddSummary(m_options.m_name, script_format, eNamedSummary, m_options.m_category, &error); 1668 if (error.Fail()) 1669 { 1670 result.AppendError(error.AsCString()); 1671 result.AppendError("added to types, but not given a name"); 1672 result.SetStatus(eReturnStatusFailed); 1673 return false; 1674 } 1675 } 1676 1677 return result.Succeeded(); 1678 } 1679 1680 #endif // LLDB_DISABLE_PYTHON 1681 1682 bool 1683 CommandObjectTypeSummaryAdd::Execute_StringSummary (Args& command, CommandReturnObject &result) 1684 { 1685 const size_t argc = command.GetArgumentCount(); 1686 1687 if (argc < 1 && !m_options.m_name) 1688 { 1689 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 1690 result.SetStatus(eReturnStatusFailed); 1691 return false; 1692 } 1693 1694 if (!m_options.m_flags.GetShowMembersOneLiner() && m_options.m_format_string.empty()) 1695 { 1696 result.AppendError("empty summary strings not allowed"); 1697 result.SetStatus(eReturnStatusFailed); 1698 return false; 1699 } 1700 1701 const char* format_cstr = (m_options.m_flags.GetShowMembersOneLiner() ? "" : m_options.m_format_string.c_str()); 1702 1703 // ${var%S} is an endless recursion, prevent it 1704 if (strcmp(format_cstr, "${var%S}") == 0) 1705 { 1706 result.AppendError("recursive summary not allowed"); 1707 result.SetStatus(eReturnStatusFailed); 1708 return false; 1709 } 1710 1711 Error error; 1712 1713 lldb::TypeSummaryImplSP entry(new StringSummaryFormat(m_options.m_flags, 1714 format_cstr)); 1715 1716 if (error.Fail()) 1717 { 1718 result.AppendError(error.AsCString()); 1719 result.SetStatus(eReturnStatusFailed); 1720 return false; 1721 } 1722 1723 // now I have a valid format, let's add it to every type 1724 1725 for (size_t i = 0; i < argc; i++) 1726 { 1727 const char* typeA = command.GetArgumentAtIndex(i); 1728 if (!typeA || typeA[0] == '\0') 1729 { 1730 result.AppendError("empty typenames not allowed"); 1731 result.SetStatus(eReturnStatusFailed); 1732 return false; 1733 } 1734 ConstString typeCS(typeA); 1735 1736 AddSummary(typeCS, 1737 entry, 1738 (m_options.m_regex ? eRegexSummary : eRegularSummary), 1739 m_options.m_category, 1740 &error); 1741 1742 if (error.Fail()) 1743 { 1744 result.AppendError(error.AsCString()); 1745 result.SetStatus(eReturnStatusFailed); 1746 return false; 1747 } 1748 } 1749 1750 if (m_options.m_name) 1751 { 1752 AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category, &error); 1753 if (error.Fail()) 1754 { 1755 result.AppendError(error.AsCString()); 1756 result.AppendError("added to types, but not given a name"); 1757 result.SetStatus(eReturnStatusFailed); 1758 return false; 1759 } 1760 } 1761 1762 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1763 return result.Succeeded(); 1764 } 1765 1766 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter) : 1767 CommandObjectParsed(interpreter, 1768 "type summary add", 1769 "Add a new summary style for a type.", 1770 nullptr), 1771 IOHandlerDelegateMultiline ("DONE"), 1772 m_options (interpreter) 1773 { 1774 CommandArgumentEntry type_arg; 1775 CommandArgumentData type_style_arg; 1776 1777 type_style_arg.arg_type = eArgTypeName; 1778 type_style_arg.arg_repetition = eArgRepeatPlus; 1779 1780 type_arg.push_back (type_style_arg); 1781 1782 m_arguments.push_back (type_arg); 1783 1784 SetHelpLong( 1785 R"( 1786 The following examples of 'type summary add' refer to this code snippet for context: 1787 1788 struct JustADemo 1789 { 1790 int* ptr; 1791 float value; 1792 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {} 1793 }; 1794 JustADemo demo_instance(42, 3.14); 1795 1796 typedef JustADemo NewDemo; 1797 NewDemo new_demo_instance(42, 3.14); 1798 1799 (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo 1800 1801 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42" 1802 1803 (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo 1804 1805 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14" 1806 1807 )" "Alternatively, you could define formatting for all pointers to integers and \ 1808 rely on that when formatting JustADemo to obtain the same result:" R"( 1809 1810 (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *" 1811 (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo 1812 1813 )" "Type summaries are automatically applied to derived typedefs, so the examples \ 1814 above apply to both JustADemo and NewDemo. The cascade option can be used to \ 1815 suppress this behavior:" R"( 1816 1817 (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no 1818 1819 The summary will now be used for values of JustADemo but not NewDemo. 1820 1821 )" "By default summaries are shown for pointers and references to values of the \ 1822 specified type. To suppress formatting for pointers use the -p option, or apply \ 1823 the corresponding -r option to suppress formatting for references:" R"( 1824 1825 (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo 1826 1827 )" "One-line summaries including all fields in a type can be inferred without supplying an \ 1828 explicit summary string by passing the -c option:" R"( 1829 1830 (lldb) type summary add -c JustADemo 1831 (lldb) frame variable demo_instance 1832 (ptr=<address>, value=3.14) 1833 1834 )" "Type summaries normally suppress the nested display of individual fields. To \ 1835 supply a summary to supplement the default structure add the -e option:" R"( 1836 1837 (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo 1838 1839 )" "Now when displaying JustADemo values the int* is displayed, followed by the \ 1840 standard LLDB sequence of children, one per line:" R"( 1841 1842 *ptr = 42 { 1843 ptr = <address> 1844 value = 3.14 1845 } 1846 1847 )" "You can also add summaries written in Python. These scripts use lldb public API to \ 1848 gather information from your variables and produce a meaningful summary. To start a \ 1849 multi-line script use the -P option. The function declaration will be displayed along with \ 1850 a comment describing the two arguments. End your script with the word 'DONE' on a line by \ 1851 itself:" R"( 1852 1853 (lldb) type summary add JustADemo -P 1854 def function (valobj,internal_dict): 1855 """valobj: an SBValue which you want to provide a summary for 1856 internal_dict: an LLDB support object not to be used""" 1857 value = valobj.GetChildMemberWithName('value'); 1858 return 'My value is ' + value.GetValue(); 1859 DONE 1860 1861 Alternatively, the -o option can be used when providing a simple one-line Python script: 1862 1863 (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")" 1864 ); 1865 } 1866 1867 bool 1868 CommandObjectTypeSummaryAdd::DoExecute (Args& command, CommandReturnObject &result) 1869 { 1870 WarnOnPotentialUnquotedUnsignedType(command, result); 1871 1872 if (m_options.m_is_add_script) 1873 { 1874 #ifndef LLDB_DISABLE_PYTHON 1875 return Execute_ScriptSummary(command, result); 1876 #else 1877 result.AppendError ("python is disabled"); 1878 result.SetStatus(eReturnStatusFailed); 1879 return false; 1880 #endif // LLDB_DISABLE_PYTHON 1881 } 1882 1883 return Execute_StringSummary(command, result); 1884 } 1885 1886 static bool 1887 FixArrayTypeNameWithRegex (ConstString &type_name) 1888 { 1889 llvm::StringRef type_name_ref(type_name.GetStringRef()); 1890 1891 if (type_name_ref.endswith("[]")) 1892 { 1893 std::string type_name_str(type_name.GetCString()); 1894 type_name_str.resize(type_name_str.length()-2); 1895 if (type_name_str.back() != ' ') 1896 type_name_str.append(" \\[[0-9]+\\]"); 1897 else 1898 type_name_str.append("\\[[0-9]+\\]"); 1899 type_name.SetCString(type_name_str.c_str()); 1900 return true; 1901 } 1902 return false; 1903 } 1904 1905 bool 1906 CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, 1907 TypeSummaryImplSP entry, 1908 SummaryFormatType type, 1909 std::string category_name, 1910 Error* error) 1911 { 1912 lldb::TypeCategoryImplSP category; 1913 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); 1914 1915 if (type == eRegularSummary) 1916 { 1917 if (FixArrayTypeNameWithRegex (type_name)) 1918 type = eRegexSummary; 1919 } 1920 1921 if (type == eRegexSummary) 1922 { 1923 RegularExpressionSP typeRX(new RegularExpression()); 1924 if (!typeRX->Compile(type_name.GetCString())) 1925 { 1926 if (error) 1927 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 1928 return false; 1929 } 1930 1931 category->GetRegexTypeSummariesContainer()->Delete(type_name); 1932 category->GetRegexTypeSummariesContainer()->Add(typeRX, entry); 1933 1934 return true; 1935 } 1936 else if (type == eNamedSummary) 1937 { 1938 // system named summaries do not exist (yet?) 1939 DataVisualization::NamedSummaryFormats::Add(type_name,entry); 1940 return true; 1941 } 1942 else 1943 { 1944 category->GetTypeSummariesContainer()->Add(type_name, entry); 1945 return true; 1946 } 1947 } 1948 1949 OptionDefinition 1950 CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = 1951 { 1952 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 1953 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, 1954 { 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."}, 1955 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 1956 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 1957 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions."}, 1958 { LLDB_OPT_SET_1 , true, "inline-children", 'c', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If true, inline all child values into summary string."}, 1959 { LLDB_OPT_SET_1 , false, "omit-names", 'O', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If true, omit value names in the summary display."}, 1960 { LLDB_OPT_SET_2 , true, "summary-string", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeSummaryString, "Summary string used to display text and object contents."}, 1961 { 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."}, 1962 { 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."}, 1963 { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Input Python code to use for this type manually."}, 1964 { 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."}, 1965 { 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."}, 1966 { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "A name for this summary string."}, 1967 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 1968 }; 1969 1970 //------------------------------------------------------------------------- 1971 // CommandObjectTypeSummaryDelete 1972 //------------------------------------------------------------------------- 1973 1974 class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete 1975 { 1976 public: 1977 CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) : 1978 CommandObjectTypeFormatterDelete (interpreter, 1979 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, 1980 "type summary delete", 1981 "Delete an existing summary for a type.") 1982 { 1983 } 1984 1985 ~CommandObjectTypeSummaryDelete() override = default; 1986 1987 protected: 1988 bool 1989 FormatterSpecificDeletion (ConstString typeCS) override 1990 { 1991 if (m_options.m_language != lldb::eLanguageTypeUnknown) 1992 return false; 1993 return DataVisualization::NamedSummaryFormats::Delete(typeCS); 1994 } 1995 }; 1996 1997 class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear 1998 { 1999 public: 2000 CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) : 2001 CommandObjectTypeFormatterClear (interpreter, 2002 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, 2003 "type summary clear", 2004 "Delete all existing summaries.") 2005 { 2006 } 2007 2008 protected: 2009 void 2010 FormatterSpecificDeletion () override 2011 { 2012 DataVisualization::NamedSummaryFormats::Clear(); 2013 } 2014 }; 2015 2016 //------------------------------------------------------------------------- 2017 // CommandObjectTypeSummaryList 2018 //------------------------------------------------------------------------- 2019 2020 class CommandObjectTypeSummaryList : public CommandObjectTypeFormatterList<TypeSummaryImpl> 2021 { 2022 public: 2023 CommandObjectTypeSummaryList (CommandInterpreter &interpreter) : 2024 CommandObjectTypeFormatterList(interpreter, 2025 "type summary list", 2026 "Show a list of current summaries.") 2027 { 2028 } 2029 2030 protected: 2031 void 2032 FormatterSpecificList (CommandReturnObject &result) override 2033 { 2034 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) 2035 { 2036 result.GetOutputStream().Printf("Named summaries:\n"); 2037 DataVisualization::NamedSummaryFormats::ForEach( [&result] (ConstString name, const TypeSummaryImplSP& summary_sp) -> bool { 2038 result.GetOutputStream().Printf ("%s: %s\n", name.AsCString(), summary_sp->GetDescription().c_str()); 2039 return true; 2040 }); 2041 } 2042 } 2043 }; 2044 2045 //------------------------------------------------------------------------- 2046 // CommandObjectTypeCategoryDefine 2047 //------------------------------------------------------------------------- 2048 2049 class CommandObjectTypeCategoryDefine : public CommandObjectParsed 2050 { 2051 class CommandOptions : public Options 2052 { 2053 public: 2054 CommandOptions (CommandInterpreter &interpreter) : 2055 Options (interpreter), 2056 m_define_enabled(false,false), 2057 m_cate_language(eLanguageTypeUnknown,eLanguageTypeUnknown) 2058 { 2059 } 2060 2061 ~CommandOptions() override = default; 2062 2063 Error 2064 SetOptionValue (uint32_t option_idx, const char *option_arg) override 2065 { 2066 Error error; 2067 const int short_option = m_getopt_table[option_idx].val; 2068 2069 switch (short_option) 2070 { 2071 case 'e': 2072 m_define_enabled.SetValueFromString("true"); 2073 break; 2074 case 'l': 2075 error = m_cate_language.SetValueFromString(option_arg); 2076 break; 2077 default: 2078 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2079 break; 2080 } 2081 2082 return error; 2083 } 2084 2085 void 2086 OptionParsingStarting () override 2087 { 2088 m_define_enabled.Clear(); 2089 m_cate_language.Clear(); 2090 } 2091 2092 const OptionDefinition* 2093 GetDefinitions () override 2094 { 2095 return g_option_table; 2096 } 2097 2098 // Options table: Required for subclasses of Options. 2099 2100 static OptionDefinition g_option_table[]; 2101 2102 // Instance variables to hold the values for command options. 2103 2104 OptionValueBoolean m_define_enabled; 2105 OptionValueLanguage m_cate_language; 2106 }; 2107 2108 CommandOptions m_options; 2109 2110 Options * 2111 GetOptions () override 2112 { 2113 return &m_options; 2114 } 2115 2116 public: 2117 CommandObjectTypeCategoryDefine (CommandInterpreter &interpreter) : 2118 CommandObjectParsed(interpreter, 2119 "type category define", 2120 "Define a new category as a source of formatters.", 2121 nullptr), 2122 m_options(interpreter) 2123 { 2124 CommandArgumentEntry type_arg; 2125 CommandArgumentData type_style_arg; 2126 2127 type_style_arg.arg_type = eArgTypeName; 2128 type_style_arg.arg_repetition = eArgRepeatPlus; 2129 2130 type_arg.push_back (type_style_arg); 2131 2132 m_arguments.push_back (type_arg); 2133 } 2134 2135 ~CommandObjectTypeCategoryDefine() override = default; 2136 2137 protected: 2138 bool 2139 DoExecute (Args& command, CommandReturnObject &result) override 2140 { 2141 const size_t argc = command.GetArgumentCount(); 2142 2143 if (argc < 1) 2144 { 2145 result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str()); 2146 result.SetStatus(eReturnStatusFailed); 2147 return false; 2148 } 2149 2150 for (size_t i = 0; i < argc; i++) 2151 { 2152 const char* cateName = command.GetArgumentAtIndex(i); 2153 TypeCategoryImplSP category_sp; 2154 if (DataVisualization::Categories::GetCategory(ConstString(cateName), category_sp) && category_sp) 2155 { 2156 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue()); 2157 if (m_options.m_define_enabled.GetCurrentValue()) 2158 DataVisualization::Categories::Enable(category_sp, TypeCategoryMap::Default); 2159 } 2160 } 2161 2162 result.SetStatus(eReturnStatusSuccessFinishResult); 2163 return result.Succeeded(); 2164 } 2165 }; 2166 2167 OptionDefinition 2168 CommandObjectTypeCategoryDefine::CommandOptions::g_option_table[] = 2169 { 2170 { LLDB_OPT_SET_ALL, false, "enabled", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If specified, this category will be created enabled."}, 2171 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specify the language that this category is supported for."}, 2172 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 2173 }; 2174 2175 //------------------------------------------------------------------------- 2176 // CommandObjectTypeCategoryEnable 2177 //------------------------------------------------------------------------- 2178 2179 class CommandObjectTypeCategoryEnable : public CommandObjectParsed 2180 { 2181 class CommandOptions : public Options 2182 { 2183 public: 2184 CommandOptions (CommandInterpreter &interpreter) : 2185 Options (interpreter) 2186 { 2187 } 2188 2189 ~CommandOptions() override = default; 2190 2191 Error 2192 SetOptionValue (uint32_t option_idx, const char *option_arg) override 2193 { 2194 Error error; 2195 const int short_option = m_getopt_table[option_idx].val; 2196 2197 switch (short_option) 2198 { 2199 case 'l': 2200 if (option_arg) 2201 { 2202 m_language = Language::GetLanguageTypeFromString(option_arg); 2203 if (m_language == lldb::eLanguageTypeUnknown) 2204 error.SetErrorStringWithFormat ("unrecognized language '%s'", option_arg); 2205 } 2206 break; 2207 default: 2208 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2209 break; 2210 } 2211 2212 return error; 2213 } 2214 2215 void 2216 OptionParsingStarting () override 2217 { 2218 m_language = lldb::eLanguageTypeUnknown; 2219 } 2220 2221 const OptionDefinition* 2222 GetDefinitions () override 2223 { 2224 return g_option_table; 2225 } 2226 2227 // Options table: Required for subclasses of Options. 2228 2229 static OptionDefinition g_option_table[]; 2230 2231 // Instance variables to hold the values for command options. 2232 2233 lldb::LanguageType m_language; 2234 2235 }; 2236 2237 CommandOptions m_options; 2238 2239 Options * 2240 GetOptions () override 2241 { 2242 return &m_options; 2243 } 2244 2245 public: 2246 CommandObjectTypeCategoryEnable (CommandInterpreter &interpreter) : 2247 CommandObjectParsed(interpreter, 2248 "type category enable", 2249 "Enable a category as a source of formatters.", 2250 nullptr), 2251 m_options(interpreter) 2252 { 2253 CommandArgumentEntry type_arg; 2254 CommandArgumentData type_style_arg; 2255 2256 type_style_arg.arg_type = eArgTypeName; 2257 type_style_arg.arg_repetition = eArgRepeatPlus; 2258 2259 type_arg.push_back (type_style_arg); 2260 2261 m_arguments.push_back (type_arg); 2262 2263 } 2264 2265 ~CommandObjectTypeCategoryEnable() override = default; 2266 2267 protected: 2268 bool 2269 DoExecute (Args& command, CommandReturnObject &result) override 2270 { 2271 const size_t argc = command.GetArgumentCount(); 2272 2273 if (argc < 1 && 2274 m_options.m_language == lldb::eLanguageTypeUnknown) 2275 { 2276 result.AppendErrorWithFormat ("%s takes arguments and/or a language", m_cmd_name.c_str()); 2277 result.SetStatus(eReturnStatusFailed); 2278 return false; 2279 } 2280 2281 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0) 2282 { 2283 DataVisualization::Categories::EnableStar(); 2284 } 2285 else if (argc > 0) 2286 { 2287 for (int i = argc - 1; i >= 0; i--) 2288 { 2289 const char* typeA = command.GetArgumentAtIndex(i); 2290 ConstString typeCS(typeA); 2291 2292 if (!typeCS) 2293 { 2294 result.AppendError("empty category name not allowed"); 2295 result.SetStatus(eReturnStatusFailed); 2296 return false; 2297 } 2298 DataVisualization::Categories::Enable(typeCS); 2299 lldb::TypeCategoryImplSP cate; 2300 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) 2301 { 2302 if (cate->GetCount() == 0) 2303 { 2304 result.AppendWarning("empty category enabled (typo?)"); 2305 } 2306 } 2307 } 2308 } 2309 2310 if (m_options.m_language != lldb::eLanguageTypeUnknown) 2311 DataVisualization::Categories::Enable(m_options.m_language); 2312 2313 result.SetStatus(eReturnStatusSuccessFinishResult); 2314 return result.Succeeded(); 2315 } 2316 }; 2317 2318 OptionDefinition 2319 CommandObjectTypeCategoryEnable::CommandOptions::g_option_table[] = 2320 { 2321 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Enable the category for this language."}, 2322 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 2323 }; 2324 2325 //------------------------------------------------------------------------- 2326 // CommandObjectTypeCategoryDelete 2327 //------------------------------------------------------------------------- 2328 2329 class CommandObjectTypeCategoryDelete : public CommandObjectParsed 2330 { 2331 public: 2332 CommandObjectTypeCategoryDelete (CommandInterpreter &interpreter) : 2333 CommandObjectParsed(interpreter, 2334 "type category delete", 2335 "Delete a category and all associated formatters.", 2336 nullptr) 2337 { 2338 CommandArgumentEntry type_arg; 2339 CommandArgumentData type_style_arg; 2340 2341 type_style_arg.arg_type = eArgTypeName; 2342 type_style_arg.arg_repetition = eArgRepeatPlus; 2343 2344 type_arg.push_back (type_style_arg); 2345 2346 m_arguments.push_back (type_arg); 2347 } 2348 2349 ~CommandObjectTypeCategoryDelete() override = default; 2350 2351 protected: 2352 bool 2353 DoExecute (Args& command, CommandReturnObject &result) override 2354 { 2355 const size_t argc = command.GetArgumentCount(); 2356 2357 if (argc < 1) 2358 { 2359 result.AppendErrorWithFormat ("%s takes 1 or more arg.\n", m_cmd_name.c_str()); 2360 result.SetStatus(eReturnStatusFailed); 2361 return false; 2362 } 2363 2364 bool success = true; 2365 2366 // the order is not relevant here 2367 for (int i = argc - 1; i >= 0; i--) 2368 { 2369 const char* typeA = command.GetArgumentAtIndex(i); 2370 ConstString typeCS(typeA); 2371 2372 if (!typeCS) 2373 { 2374 result.AppendError("empty category name not allowed"); 2375 result.SetStatus(eReturnStatusFailed); 2376 return false; 2377 } 2378 if (!DataVisualization::Categories::Delete(typeCS)) 2379 success = false; // keep deleting even if we hit an error 2380 } 2381 if (success) 2382 { 2383 result.SetStatus(eReturnStatusSuccessFinishResult); 2384 return result.Succeeded(); 2385 } 2386 else 2387 { 2388 result.AppendError("cannot delete one or more categories\n"); 2389 result.SetStatus(eReturnStatusFailed); 2390 return false; 2391 } 2392 } 2393 }; 2394 2395 //------------------------------------------------------------------------- 2396 // CommandObjectTypeCategoryDisable 2397 //------------------------------------------------------------------------- 2398 2399 class CommandObjectTypeCategoryDisable : public CommandObjectParsed 2400 { 2401 class CommandOptions : public Options 2402 { 2403 public: 2404 CommandOptions (CommandInterpreter &interpreter) : 2405 Options (interpreter) 2406 { 2407 } 2408 2409 ~CommandOptions() override = default; 2410 2411 Error 2412 SetOptionValue (uint32_t option_idx, const char *option_arg) override 2413 { 2414 Error error; 2415 const int short_option = m_getopt_table[option_idx].val; 2416 2417 switch (short_option) 2418 { 2419 case 'l': 2420 if (option_arg) 2421 { 2422 m_language = Language::GetLanguageTypeFromString(option_arg); 2423 if (m_language == lldb::eLanguageTypeUnknown) 2424 error.SetErrorStringWithFormat ("unrecognized language '%s'", option_arg); 2425 } 2426 break; 2427 default: 2428 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2429 break; 2430 } 2431 2432 return error; 2433 } 2434 2435 void 2436 OptionParsingStarting () override 2437 { 2438 m_language = lldb::eLanguageTypeUnknown; 2439 } 2440 2441 const OptionDefinition* 2442 GetDefinitions () override 2443 { 2444 return g_option_table; 2445 } 2446 2447 // Options table: Required for subclasses of Options. 2448 2449 static OptionDefinition g_option_table[]; 2450 2451 // Instance variables to hold the values for command options. 2452 2453 lldb::LanguageType m_language; 2454 }; 2455 2456 CommandOptions m_options; 2457 2458 Options * 2459 GetOptions () override 2460 { 2461 return &m_options; 2462 } 2463 2464 public: 2465 CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) : 2466 CommandObjectParsed(interpreter, 2467 "type category disable", 2468 "Disable a category as a source of formatters.", 2469 nullptr), 2470 m_options(interpreter) 2471 { 2472 CommandArgumentEntry type_arg; 2473 CommandArgumentData type_style_arg; 2474 2475 type_style_arg.arg_type = eArgTypeName; 2476 type_style_arg.arg_repetition = eArgRepeatPlus; 2477 2478 type_arg.push_back (type_style_arg); 2479 2480 m_arguments.push_back (type_arg); 2481 } 2482 2483 ~CommandObjectTypeCategoryDisable() override = default; 2484 2485 protected: 2486 bool 2487 DoExecute (Args& command, CommandReturnObject &result) override 2488 { 2489 const size_t argc = command.GetArgumentCount(); 2490 2491 if (argc < 1 && 2492 m_options.m_language == lldb::eLanguageTypeUnknown) 2493 { 2494 result.AppendErrorWithFormat ("%s takes arguments and/or a language", m_cmd_name.c_str()); 2495 result.SetStatus(eReturnStatusFailed); 2496 return false; 2497 } 2498 2499 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0) 2500 { 2501 DataVisualization::Categories::DisableStar(); 2502 } 2503 else if (argc > 0) 2504 { 2505 // the order is not relevant here 2506 for (int i = argc - 1; i >= 0; i--) 2507 { 2508 const char* typeA = command.GetArgumentAtIndex(i); 2509 ConstString typeCS(typeA); 2510 2511 if (!typeCS) 2512 { 2513 result.AppendError("empty category name not allowed"); 2514 result.SetStatus(eReturnStatusFailed); 2515 return false; 2516 } 2517 DataVisualization::Categories::Disable(typeCS); 2518 } 2519 } 2520 2521 if (m_options.m_language != lldb::eLanguageTypeUnknown) 2522 DataVisualization::Categories::Disable(m_options.m_language); 2523 2524 result.SetStatus(eReturnStatusSuccessFinishResult); 2525 return result.Succeeded(); 2526 } 2527 }; 2528 2529 OptionDefinition 2530 CommandObjectTypeCategoryDisable::CommandOptions::g_option_table[] = 2531 { 2532 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Enable the category for this language."}, 2533 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 2534 }; 2535 2536 //------------------------------------------------------------------------- 2537 // CommandObjectTypeCategoryList 2538 //------------------------------------------------------------------------- 2539 2540 class CommandObjectTypeCategoryList : public CommandObjectParsed 2541 { 2542 public: 2543 CommandObjectTypeCategoryList (CommandInterpreter &interpreter) : 2544 CommandObjectParsed(interpreter, 2545 "type category list", 2546 "Provide a list of all existing categories.", 2547 nullptr) 2548 { 2549 CommandArgumentEntry type_arg; 2550 CommandArgumentData type_style_arg; 2551 2552 type_style_arg.arg_type = eArgTypeName; 2553 type_style_arg.arg_repetition = eArgRepeatOptional; 2554 2555 type_arg.push_back (type_style_arg); 2556 2557 m_arguments.push_back (type_arg); 2558 } 2559 2560 ~CommandObjectTypeCategoryList() override = default; 2561 2562 protected: 2563 bool 2564 DoExecute (Args& command, CommandReturnObject &result) override 2565 { 2566 const size_t argc = command.GetArgumentCount(); 2567 2568 std::unique_ptr<RegularExpression> regex; 2569 2570 if (argc == 1) 2571 { 2572 regex.reset(new RegularExpression()); 2573 const char* arg = command.GetArgumentAtIndex(0); 2574 if (!regex->Compile(arg)) 2575 { 2576 result.AppendErrorWithFormat("syntax error in category regular expression '%s'", arg); 2577 result.SetStatus(eReturnStatusFailed); 2578 return false; 2579 } 2580 } 2581 else if (argc != 0) 2582 { 2583 result.AppendErrorWithFormat ("%s takes 0 or one arg.\n", m_cmd_name.c_str()); 2584 result.SetStatus(eReturnStatusFailed); 2585 return false; 2586 } 2587 2588 DataVisualization::Categories::ForEach( [®ex, &result] (const lldb::TypeCategoryImplSP& category_sp) -> bool { 2589 if (regex) 2590 { 2591 bool escape = true; 2592 if (0 == strcmp(category_sp->GetName(), regex->GetText())) 2593 { 2594 escape = false; 2595 } 2596 else if (regex->Execute(category_sp->GetName())) 2597 { 2598 escape = false; 2599 } 2600 2601 if (escape) 2602 return true; 2603 } 2604 2605 result.GetOutputStream().Printf("Category: %s\n", category_sp->GetDescription().c_str()); 2606 2607 return true; 2608 }); 2609 2610 result.SetStatus(eReturnStatusSuccessFinishResult); 2611 return result.Succeeded(); 2612 } 2613 }; 2614 2615 //------------------------------------------------------------------------- 2616 // CommandObjectTypeFilterList 2617 //------------------------------------------------------------------------- 2618 2619 class CommandObjectTypeFilterList : public CommandObjectTypeFormatterList<TypeFilterImpl> 2620 { 2621 public: 2622 CommandObjectTypeFilterList (CommandInterpreter &interpreter) : 2623 CommandObjectTypeFormatterList(interpreter, 2624 "type filter list", 2625 "Show a list of current filters.") 2626 { 2627 } 2628 }; 2629 2630 #ifndef LLDB_DISABLE_PYTHON 2631 2632 //------------------------------------------------------------------------- 2633 // CommandObjectTypeSynthList 2634 //------------------------------------------------------------------------- 2635 2636 class CommandObjectTypeSynthList : public CommandObjectTypeFormatterList<SyntheticChildren> 2637 { 2638 public: 2639 CommandObjectTypeSynthList (CommandInterpreter &interpreter) : 2640 CommandObjectTypeFormatterList(interpreter, 2641 "type synthetic list", 2642 "Show a list of current synthetic providers.") 2643 { 2644 } 2645 }; 2646 2647 #endif // LLDB_DISABLE_PYTHON 2648 2649 //------------------------------------------------------------------------- 2650 // CommandObjectTypeFilterDelete 2651 //------------------------------------------------------------------------- 2652 2653 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete 2654 { 2655 public: 2656 CommandObjectTypeFilterDelete (CommandInterpreter &interpreter) : 2657 CommandObjectTypeFormatterDelete (interpreter, 2658 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2659 "type filter delete", 2660 "Delete an existing filter for a type.") 2661 { 2662 } 2663 2664 ~CommandObjectTypeFilterDelete() override = default; 2665 }; 2666 2667 #ifndef LLDB_DISABLE_PYTHON 2668 2669 //------------------------------------------------------------------------- 2670 // CommandObjectTypeSynthDelete 2671 //------------------------------------------------------------------------- 2672 2673 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete 2674 { 2675 public: 2676 CommandObjectTypeSynthDelete (CommandInterpreter &interpreter) : 2677 CommandObjectTypeFormatterDelete (interpreter, 2678 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 2679 "type synthetic delete", 2680 "Delete an existing synthetic provider for a type.") 2681 { 2682 } 2683 2684 ~CommandObjectTypeSynthDelete() override = default; 2685 }; 2686 2687 #endif // LLDB_DISABLE_PYTHON 2688 2689 //------------------------------------------------------------------------- 2690 // CommandObjectTypeFilterClear 2691 //------------------------------------------------------------------------- 2692 2693 class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear 2694 { 2695 public: 2696 CommandObjectTypeFilterClear (CommandInterpreter &interpreter) : 2697 CommandObjectTypeFormatterClear (interpreter, 2698 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2699 "type filter clear", 2700 "Delete all existing filter.") 2701 { 2702 } 2703 }; 2704 2705 #ifndef LLDB_DISABLE_PYTHON 2706 //------------------------------------------------------------------------- 2707 // CommandObjectTypeSynthClear 2708 //------------------------------------------------------------------------- 2709 2710 class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear 2711 { 2712 public: 2713 CommandObjectTypeSynthClear (CommandInterpreter &interpreter) : 2714 CommandObjectTypeFormatterClear (interpreter, 2715 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 2716 "type synthetic clear", 2717 "Delete all existing synthetic providers.") 2718 { 2719 } 2720 }; 2721 2722 bool 2723 CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result) 2724 { 2725 SynthAddOptions *options = new SynthAddOptions ( m_options.m_skip_pointers, 2726 m_options.m_skip_references, 2727 m_options.m_cascade, 2728 m_options.m_regex, 2729 m_options.m_category); 2730 2731 const size_t argc = command.GetArgumentCount(); 2732 2733 for (size_t i = 0; i < argc; i++) 2734 { 2735 const char* typeA = command.GetArgumentAtIndex(i); 2736 if (typeA && *typeA) 2737 options->m_target_types << typeA; 2738 else 2739 { 2740 result.AppendError("empty typenames not allowed"); 2741 result.SetStatus(eReturnStatusFailed); 2742 return false; 2743 } 2744 } 2745 2746 m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt 2747 *this, // IOHandlerDelegate 2748 true, // Run IOHandler in async mode 2749 options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions 2750 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2751 return result.Succeeded(); 2752 } 2753 2754 bool 2755 CommandObjectTypeSynthAdd::Execute_PythonClass (Args& command, CommandReturnObject &result) 2756 { 2757 const size_t argc = command.GetArgumentCount(); 2758 2759 if (argc < 1) 2760 { 2761 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 2762 result.SetStatus(eReturnStatusFailed); 2763 return false; 2764 } 2765 2766 if (m_options.m_class_name.empty() && !m_options.m_input_python) 2767 { 2768 result.AppendErrorWithFormat ("%s needs either a Python class name or -P to directly input Python code.\n", m_cmd_name.c_str()); 2769 result.SetStatus(eReturnStatusFailed); 2770 return false; 2771 } 2772 2773 SyntheticChildrenSP entry; 2774 2775 ScriptedSyntheticChildren* impl = new ScriptedSyntheticChildren(SyntheticChildren::Flags(). 2776 SetCascades(m_options.m_cascade). 2777 SetSkipPointers(m_options.m_skip_pointers). 2778 SetSkipReferences(m_options.m_skip_references), 2779 m_options.m_class_name.c_str()); 2780 2781 entry.reset(impl); 2782 2783 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 2784 2785 if (interpreter && !interpreter->CheckObjectExists(impl->GetPythonClassName())) 2786 result.AppendWarning("The provided class does not exist - please define it before attempting to use this synthetic provider"); 2787 2788 // now I have a valid provider, let's add it to every type 2789 2790 lldb::TypeCategoryImplSP category; 2791 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 2792 2793 Error error; 2794 2795 for (size_t i = 0; i < argc; i++) 2796 { 2797 const char* typeA = command.GetArgumentAtIndex(i); 2798 ConstString typeCS(typeA); 2799 if (typeCS) 2800 { 2801 if (!AddSynth(typeCS, 2802 entry, 2803 m_options.m_regex ? eRegexSynth : eRegularSynth, 2804 m_options.m_category, 2805 &error)) 2806 { 2807 result.AppendError(error.AsCString()); 2808 result.SetStatus(eReturnStatusFailed); 2809 return false; 2810 } 2811 } 2812 else 2813 { 2814 result.AppendError("empty typenames not allowed"); 2815 result.SetStatus(eReturnStatusFailed); 2816 return false; 2817 } 2818 } 2819 2820 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2821 return result.Succeeded(); 2822 } 2823 2824 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) : 2825 CommandObjectParsed(interpreter, 2826 "type synthetic add", 2827 "Add a new synthetic provider for a type.", 2828 nullptr), 2829 IOHandlerDelegateMultiline ("DONE"), 2830 m_options (interpreter) 2831 { 2832 CommandArgumentEntry type_arg; 2833 CommandArgumentData type_style_arg; 2834 2835 type_style_arg.arg_type = eArgTypeName; 2836 type_style_arg.arg_repetition = eArgRepeatPlus; 2837 2838 type_arg.push_back (type_style_arg); 2839 2840 m_arguments.push_back (type_arg); 2841 } 2842 2843 bool 2844 CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, 2845 SyntheticChildrenSP entry, 2846 SynthFormatType type, 2847 std::string category_name, 2848 Error* error) 2849 { 2850 lldb::TypeCategoryImplSP category; 2851 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); 2852 2853 if (type == eRegularSynth) 2854 { 2855 if (FixArrayTypeNameWithRegex (type_name)) 2856 type = eRegexSynth; 2857 } 2858 2859 if (category->AnyMatches(type_name, 2860 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2861 false)) 2862 { 2863 if (error) 2864 error->SetErrorStringWithFormat("cannot add synthetic for type %s when filter is defined in same category!", type_name.AsCString()); 2865 return false; 2866 } 2867 2868 if (type == eRegexSynth) 2869 { 2870 RegularExpressionSP typeRX(new RegularExpression()); 2871 if (!typeRX->Compile(type_name.GetCString())) 2872 { 2873 if (error) 2874 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 2875 return false; 2876 } 2877 2878 category->GetRegexTypeSyntheticsContainer()->Delete(type_name); 2879 category->GetRegexTypeSyntheticsContainer()->Add(typeRX, entry); 2880 2881 return true; 2882 } 2883 else 2884 { 2885 category->GetTypeSyntheticsContainer()->Add(type_name, entry); 2886 return true; 2887 } 2888 } 2889 2890 OptionDefinition 2891 CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] = 2892 { 2893 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, 2894 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 2895 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 2896 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 2897 { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children."}, 2898 { 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."}, 2899 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions."}, 2900 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 2901 }; 2902 2903 #endif // LLDB_DISABLE_PYTHON 2904 2905 class CommandObjectTypeFilterAdd : public CommandObjectParsed 2906 { 2907 private: 2908 class CommandOptions : public Options 2909 { 2910 typedef std::vector<std::string> option_vector; 2911 2912 public: 2913 CommandOptions (CommandInterpreter &interpreter) : 2914 Options (interpreter) 2915 { 2916 } 2917 2918 ~CommandOptions() override = default; 2919 2920 Error 2921 SetOptionValue (uint32_t option_idx, const char *option_arg) override 2922 { 2923 Error error; 2924 const int short_option = m_getopt_table[option_idx].val; 2925 bool success; 2926 2927 switch (short_option) 2928 { 2929 case 'C': 2930 m_cascade = Args::StringToBoolean(option_arg, true, &success); 2931 if (!success) 2932 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg); 2933 break; 2934 case 'c': 2935 m_expr_paths.push_back(option_arg); 2936 has_child_list = true; 2937 break; 2938 case 'p': 2939 m_skip_pointers = true; 2940 break; 2941 case 'r': 2942 m_skip_references = true; 2943 break; 2944 case 'w': 2945 m_category = std::string(option_arg); 2946 break; 2947 case 'x': 2948 m_regex = true; 2949 break; 2950 default: 2951 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2952 break; 2953 } 2954 2955 return error; 2956 } 2957 2958 void 2959 OptionParsingStarting () override 2960 { 2961 m_cascade = true; 2962 m_skip_pointers = false; 2963 m_skip_references = false; 2964 m_category = "default"; 2965 m_expr_paths.clear(); 2966 has_child_list = false; 2967 m_regex = false; 2968 } 2969 2970 const OptionDefinition* 2971 GetDefinitions () override 2972 { 2973 return g_option_table; 2974 } 2975 2976 // Options table: Required for subclasses of Options. 2977 2978 static OptionDefinition g_option_table[]; 2979 2980 // Instance variables to hold the values for command options. 2981 2982 bool m_cascade; 2983 bool m_skip_references; 2984 bool m_skip_pointers; 2985 bool m_input_python; 2986 option_vector m_expr_paths; 2987 std::string m_category; 2988 bool has_child_list; 2989 bool m_regex; 2990 2991 typedef option_vector::iterator ExpressionPathsIterator; 2992 }; 2993 2994 CommandOptions m_options; 2995 2996 Options * 2997 GetOptions () override 2998 { 2999 return &m_options; 3000 } 3001 3002 enum FilterFormatType 3003 { 3004 eRegularFilter, 3005 eRegexFilter 3006 }; 3007 3008 bool 3009 AddFilter(ConstString type_name, 3010 TypeFilterImplSP entry, 3011 FilterFormatType type, 3012 std::string category_name, 3013 Error* error) 3014 { 3015 lldb::TypeCategoryImplSP category; 3016 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); 3017 3018 if (type == eRegularFilter) 3019 { 3020 if (FixArrayTypeNameWithRegex (type_name)) 3021 type = eRegexFilter; 3022 } 3023 3024 if (category->AnyMatches(type_name, 3025 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 3026 false)) 3027 { 3028 if (error) 3029 error->SetErrorStringWithFormat("cannot add filter for type %s when synthetic is defined in same category!", type_name.AsCString()); 3030 return false; 3031 } 3032 3033 if (type == eRegexFilter) 3034 { 3035 RegularExpressionSP typeRX(new RegularExpression()); 3036 if (!typeRX->Compile(type_name.GetCString())) 3037 { 3038 if (error) 3039 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 3040 return false; 3041 } 3042 3043 category->GetRegexTypeFiltersContainer()->Delete(type_name); 3044 category->GetRegexTypeFiltersContainer()->Add(typeRX, entry); 3045 3046 return true; 3047 } 3048 else 3049 { 3050 category->GetTypeFiltersContainer()->Add(type_name, entry); 3051 return true; 3052 } 3053 } 3054 3055 public: 3056 CommandObjectTypeFilterAdd (CommandInterpreter &interpreter) : 3057 CommandObjectParsed(interpreter, 3058 "type filter add", 3059 "Add a new filter for a type.", 3060 nullptr), 3061 m_options (interpreter) 3062 { 3063 CommandArgumentEntry type_arg; 3064 CommandArgumentData type_style_arg; 3065 3066 type_style_arg.arg_type = eArgTypeName; 3067 type_style_arg.arg_repetition = eArgRepeatPlus; 3068 3069 type_arg.push_back (type_style_arg); 3070 3071 m_arguments.push_back (type_arg); 3072 3073 SetHelpLong( 3074 R"( 3075 The following examples of 'type filter add' refer to this code snippet for context: 3076 3077 class Foo { 3078 int a; 3079 int b; 3080 int c; 3081 int d; 3082 int e; 3083 int f; 3084 int g; 3085 int h; 3086 int i; 3087 } 3088 Foo my_foo; 3089 3090 Adding a simple filter: 3091 3092 (lldb) type filter add --child a --child g Foo 3093 (lldb) frame variable my_foo 3094 3095 )" "Produces output where only a and g are displayed. Other children of my_foo \ 3096 (b, c, d, e, f, h and i) are available by asking for them explicitly:" R"( 3097 3098 (lldb) frame variable my_foo.b my_foo.c my_foo.i 3099 3100 )" "The formatting option --raw on frame variable bypasses the filter, showing \ 3101 all children of my_foo as if no filter was defined:" R"( 3102 3103 (lldb) frame variable my_foo --raw)" 3104 ); 3105 } 3106 3107 ~CommandObjectTypeFilterAdd() override = default; 3108 3109 protected: 3110 bool 3111 DoExecute (Args& command, CommandReturnObject &result) override 3112 { 3113 const size_t argc = command.GetArgumentCount(); 3114 3115 if (argc < 1) 3116 { 3117 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 3118 result.SetStatus(eReturnStatusFailed); 3119 return false; 3120 } 3121 3122 if (m_options.m_expr_paths.empty()) 3123 { 3124 result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str()); 3125 result.SetStatus(eReturnStatusFailed); 3126 return false; 3127 } 3128 3129 TypeFilterImplSP entry(new TypeFilterImpl(SyntheticChildren::Flags().SetCascades(m_options.m_cascade). 3130 SetSkipPointers(m_options.m_skip_pointers). 3131 SetSkipReferences(m_options.m_skip_references))); 3132 3133 // go through the expression paths 3134 CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end(); 3135 3136 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++) 3137 entry->AddExpressionPath(*begin); 3138 3139 3140 // now I have a valid provider, let's add it to every type 3141 3142 lldb::TypeCategoryImplSP category; 3143 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 3144 3145 Error error; 3146 3147 WarnOnPotentialUnquotedUnsignedType(command, result); 3148 3149 for (size_t i = 0; i < argc; i++) 3150 { 3151 const char* typeA = command.GetArgumentAtIndex(i); 3152 ConstString typeCS(typeA); 3153 if (typeCS) 3154 { 3155 if (!AddFilter(typeCS, 3156 entry, 3157 m_options.m_regex ? eRegexFilter : eRegularFilter, 3158 m_options.m_category, 3159 &error)) 3160 { 3161 result.AppendError(error.AsCString()); 3162 result.SetStatus(eReturnStatusFailed); 3163 return false; 3164 } 3165 } 3166 else 3167 { 3168 result.AppendError("empty typenames not allowed"); 3169 result.SetStatus(eReturnStatusFailed); 3170 return false; 3171 } 3172 } 3173 3174 result.SetStatus(eReturnStatusSuccessFinishNoResult); 3175 return result.Succeeded(); 3176 } 3177 }; 3178 3179 OptionDefinition 3180 CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] = 3181 { 3182 { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, 3183 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 3184 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 3185 { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 3186 { LLDB_OPT_SET_ALL, false, "child", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view."}, 3187 { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions."}, 3188 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 3189 }; 3190 3191 //---------------------------------------------------------------------- 3192 // "type lookup" 3193 //---------------------------------------------------------------------- 3194 class CommandObjectTypeLookup : public CommandObjectRaw 3195 { 3196 protected: 3197 class CommandOptions : public OptionGroup 3198 { 3199 public: 3200 CommandOptions () : 3201 OptionGroup(), 3202 m_show_help(false), 3203 m_language(eLanguageTypeUnknown) 3204 {} 3205 3206 ~CommandOptions() override = default; 3207 3208 uint32_t 3209 GetNumDefinitions () override 3210 { 3211 return 3; 3212 } 3213 3214 const OptionDefinition* 3215 GetDefinitions () override 3216 { 3217 return g_option_table; 3218 } 3219 3220 Error 3221 SetOptionValue (CommandInterpreter &interpreter, 3222 uint32_t option_idx, 3223 const char *option_value) override 3224 { 3225 Error error; 3226 3227 const int short_option = g_option_table[option_idx].short_option; 3228 3229 switch (short_option) 3230 { 3231 case 'h': 3232 m_show_help = true; 3233 break; 3234 3235 case 'l': 3236 m_language = Language::GetLanguageTypeFromString(option_value); 3237 break; 3238 3239 default: 3240 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 3241 break; 3242 } 3243 3244 return error; 3245 } 3246 3247 void 3248 OptionParsingStarting (CommandInterpreter &interpreter) override 3249 { 3250 m_show_help = false; 3251 m_language = eLanguageTypeUnknown; 3252 } 3253 3254 // Options table: Required for subclasses of Options. 3255 3256 static OptionDefinition g_option_table[]; 3257 bool m_show_help; 3258 lldb::LanguageType m_language; 3259 }; 3260 3261 OptionGroupOptions m_option_group; 3262 CommandOptions m_command_options; 3263 3264 public: 3265 CommandObjectTypeLookup (CommandInterpreter &interpreter) : 3266 CommandObjectRaw (interpreter, 3267 "type lookup", 3268 "Lookup types and declarations in the current target, following language-specific naming conventions.", 3269 "type lookup <type-specifier>", 3270 eCommandRequiresTarget), 3271 m_option_group(interpreter), 3272 m_command_options() 3273 { 3274 m_option_group.Append(&m_command_options); 3275 m_option_group.Finalize(); 3276 } 3277 3278 ~CommandObjectTypeLookup() override = default; 3279 3280 Options * 3281 GetOptions () override 3282 { 3283 return &m_option_group; 3284 } 3285 3286 const char* 3287 GetHelpLong () override 3288 { 3289 if (m_cmd_help_long.empty()) 3290 { 3291 StreamString stream; 3292 // FIXME: hardcoding languages is not good 3293 lldb::LanguageType languages[] = {eLanguageTypeObjC,eLanguageTypeC_plus_plus}; 3294 3295 for(const auto lang_type : languages) 3296 { 3297 if (auto language = Language::FindPlugin(lang_type)) 3298 { 3299 if (const char* help = language->GetLanguageSpecificTypeLookupHelp()) 3300 { 3301 stream.Printf("%s\n", help); 3302 } 3303 } 3304 } 3305 3306 if (stream.GetData()) 3307 m_cmd_help_long.assign(stream.GetString()); 3308 } 3309 return this->CommandObject::GetHelpLong(); 3310 } 3311 3312 bool 3313 DoExecute (const char *raw_command_line, CommandReturnObject &result) override 3314 { 3315 if (!raw_command_line || !raw_command_line[0]) 3316 { 3317 result.SetError("type lookup cannot be invoked without a type name as argument"); 3318 return false; 3319 } 3320 3321 m_option_group.NotifyOptionParsingStarting(); 3322 3323 const char * name_of_type = nullptr; 3324 3325 if (raw_command_line[0] == '-') 3326 { 3327 // We have some options and these options MUST end with --. 3328 const char *end_options = nullptr; 3329 const char *s = raw_command_line; 3330 while (s && s[0]) 3331 { 3332 end_options = ::strstr (s, "--"); 3333 if (end_options) 3334 { 3335 end_options += 2; // Get past the "--" 3336 if (::isspace (end_options[0])) 3337 { 3338 name_of_type = end_options; 3339 while (::isspace (*name_of_type)) 3340 ++name_of_type; 3341 break; 3342 } 3343 } 3344 s = end_options; 3345 } 3346 3347 if (end_options) 3348 { 3349 Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line)); 3350 if (!ParseOptions (args, result)) 3351 return false; 3352 3353 Error error (m_option_group.NotifyOptionParsingFinished()); 3354 if (error.Fail()) 3355 { 3356 result.AppendError (error.AsCString()); 3357 result.SetStatus (eReturnStatusFailed); 3358 return false; 3359 } 3360 } 3361 } 3362 if (nullptr == name_of_type) 3363 name_of_type = raw_command_line; 3364 3365 TargetSP target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget()); 3366 const bool fill_all_in = true; 3367 ExecutionContext exe_ctx(target_sp.get(), fill_all_in); 3368 ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope(); 3369 3370 bool any_found = false; 3371 3372 std::vector<Language*> languages; 3373 3374 bool is_global_search = false; 3375 3376 if ( (is_global_search = (m_command_options.m_language == eLanguageTypeUnknown)) ) 3377 { 3378 // FIXME: hardcoding languages is not good 3379 languages.push_back(Language::FindPlugin(eLanguageTypeObjC)); 3380 languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus)); 3381 } 3382 else 3383 { 3384 languages.push_back(Language::FindPlugin(m_command_options.m_language)); 3385 } 3386 3387 // This is not the most efficient way to do this, but we support very few languages 3388 // so the cost of the sort is going to be dwarfed by the actual lookup anyway 3389 if (StackFrame* frame = m_exe_ctx.GetFramePtr()) 3390 { 3391 LanguageType lang = frame->GuessLanguage(); 3392 if (lang != eLanguageTypeUnknown) 3393 { 3394 std::sort(languages.begin(), 3395 languages.end(), 3396 [lang] (Language* lang1, 3397 Language* lang2) -> bool { 3398 if (!lang1 || !lang2) return false; 3399 LanguageType lt1 = lang1->GetLanguageType(); 3400 LanguageType lt2 = lang2->GetLanguageType(); 3401 if (lt1 == lang) return true; // make the selected frame's language come first 3402 if (lt2 == lang) return false; // make the selected frame's language come first 3403 return (lt1 < lt2); // normal comparison otherwise 3404 }); 3405 } 3406 } 3407 3408 for (Language* language : languages) 3409 { 3410 if (!language) 3411 continue; 3412 3413 if (auto scavenger = language->GetTypeScavenger()) 3414 { 3415 Language::TypeScavenger::ResultSet search_results; 3416 if (scavenger->Find(best_scope, name_of_type, search_results) > 0) 3417 { 3418 for (const auto& search_result : search_results) 3419 { 3420 if (search_result && search_result->IsValid()) 3421 { 3422 any_found = true; 3423 search_result->DumpToStream(result.GetOutputStream(), this->m_command_options.m_show_help); 3424 } 3425 } 3426 } 3427 // this is "type lookup SomeName" and we did find a match, so get out 3428 if (any_found && is_global_search) 3429 break; 3430 } 3431 } 3432 3433 if (!any_found) 3434 result.AppendMessageWithFormat("no type was found matching '%s'\n", name_of_type); 3435 3436 result.SetStatus (any_found ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusSuccessFinishNoResult); 3437 return true; 3438 } 3439 }; 3440 3441 OptionDefinition 3442 CommandObjectTypeLookup::CommandOptions::g_option_table[] = 3443 { 3444 { LLDB_OPT_SET_ALL, false, "show-help", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display available help for types"}, 3445 { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Which language's types should the search scope be"}, 3446 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 3447 }; 3448 3449 template <typename FormatterType> 3450 class CommandObjectFormatterInfo : public CommandObjectRaw 3451 { 3452 public: 3453 typedef std::function<typename FormatterType::SharedPointer(ValueObject&)> DiscoveryFunction; 3454 CommandObjectFormatterInfo (CommandInterpreter &interpreter, 3455 const char* formatter_name, 3456 DiscoveryFunction discovery_func) : 3457 CommandObjectRaw(interpreter, 3458 nullptr, 3459 nullptr, 3460 nullptr, 3461 eCommandRequiresFrame), 3462 m_formatter_name(formatter_name ? formatter_name : ""), 3463 m_discovery_function(discovery_func) 3464 { 3465 StreamString name; 3466 name.Printf("type %s info", formatter_name); 3467 SetCommandName(name.GetData()); 3468 StreamString help; 3469 help.Printf("This command evaluates the provided expression and shows which %s is applied to the resulting value (if any).", formatter_name); 3470 SetHelp(help.GetData()); 3471 StreamString syntax; 3472 syntax.Printf("type %s info <expr>", formatter_name); 3473 SetSyntax(syntax.GetData()); 3474 } 3475 3476 ~CommandObjectFormatterInfo() override = default; 3477 3478 protected: 3479 bool 3480 DoExecute (const char *command, CommandReturnObject &result) override 3481 { 3482 TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); 3483 Thread *thread = GetDefaultThread(); 3484 if (!thread) 3485 { 3486 result.AppendError("no default thread"); 3487 result.SetStatus(lldb::eReturnStatusFailed); 3488 return false; 3489 } 3490 3491 StackFrameSP frame_sp = thread->GetSelectedFrame(); 3492 ValueObjectSP result_valobj_sp; 3493 EvaluateExpressionOptions options; 3494 lldb::ExpressionResults expr_result = target_sp->EvaluateExpression(command, frame_sp.get(), result_valobj_sp, options); 3495 if (expr_result == eExpressionCompleted && result_valobj_sp) 3496 { 3497 result_valobj_sp = result_valobj_sp->GetQualifiedRepresentationIfAvailable(target_sp->GetPreferDynamicValue(), target_sp->GetEnableSyntheticValue()); 3498 typename FormatterType::SharedPointer formatter_sp = m_discovery_function(*result_valobj_sp); 3499 if (formatter_sp) 3500 { 3501 std::string description(formatter_sp->GetDescription()); 3502 result.AppendMessageWithFormat("%s applied to (%s) %s is: %s\n", 3503 m_formatter_name.c_str(), 3504 result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"), 3505 command, 3506 description.c_str()); 3507 result.SetStatus(lldb::eReturnStatusSuccessFinishResult); 3508 } 3509 else 3510 { 3511 result.AppendMessageWithFormat("no %s applies to (%s) %s\n", 3512 m_formatter_name.c_str(), 3513 result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>"), 3514 command); 3515 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 3516 } 3517 return true; 3518 } 3519 else 3520 { 3521 result.AppendError("failed to evaluate expression"); 3522 result.SetStatus(lldb::eReturnStatusFailed); 3523 return false; 3524 } 3525 } 3526 3527 private: 3528 std::string m_formatter_name; 3529 DiscoveryFunction m_discovery_function; 3530 }; 3531 3532 class CommandObjectTypeFormat : public CommandObjectMultiword 3533 { 3534 public: 3535 CommandObjectTypeFormat (CommandInterpreter &interpreter) : 3536 CommandObjectMultiword (interpreter, 3537 "type format", 3538 "A set of commands for editing variable value display options", 3539 "type format [<sub-command-options>] ") 3540 { 3541 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter))); 3542 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFormatClear (interpreter))); 3543 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter))); 3544 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFormatList (interpreter))); 3545 LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo<TypeFormatImpl>(interpreter, 3546 "format", 3547 [](ValueObject& valobj) -> TypeFormatImpl::SharedPointer { 3548 return valobj.GetValueFormat(); 3549 }))); 3550 } 3551 3552 ~CommandObjectTypeFormat() override = default; 3553 }; 3554 3555 #ifndef LLDB_DISABLE_PYTHON 3556 3557 class CommandObjectTypeSynth : public CommandObjectMultiword 3558 { 3559 public: 3560 CommandObjectTypeSynth (CommandInterpreter &interpreter) : 3561 CommandObjectMultiword (interpreter, 3562 "type synthetic", 3563 "A set of commands for operating on synthetic type representations", 3564 "type synthetic [<sub-command-options>] ") 3565 { 3566 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSynthAdd (interpreter))); 3567 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSynthClear (interpreter))); 3568 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSynthDelete (interpreter))); 3569 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSynthList (interpreter))); 3570 LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo<SyntheticChildren>(interpreter, 3571 "synthetic", 3572 [](ValueObject& valobj) -> SyntheticChildren::SharedPointer { 3573 return valobj.GetSyntheticChildren(); 3574 }))); 3575 } 3576 3577 ~CommandObjectTypeSynth() override = default; 3578 }; 3579 3580 #endif // LLDB_DISABLE_PYTHON 3581 3582 class CommandObjectTypeFilter : public CommandObjectMultiword 3583 { 3584 public: 3585 CommandObjectTypeFilter (CommandInterpreter &interpreter) : 3586 CommandObjectMultiword (interpreter, 3587 "type filter", 3588 "A set of commands for operating on type filters", 3589 "type synthetic [<sub-command-options>] ") 3590 { 3591 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeFilterAdd (interpreter))); 3592 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFilterClear (interpreter))); 3593 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFilterDelete (interpreter))); 3594 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFilterList (interpreter))); 3595 } 3596 3597 ~CommandObjectTypeFilter() override = default; 3598 }; 3599 3600 class CommandObjectTypeCategory : public CommandObjectMultiword 3601 { 3602 public: 3603 CommandObjectTypeCategory (CommandInterpreter &interpreter) : 3604 CommandObjectMultiword (interpreter, 3605 "type category", 3606 "A set of commands for operating on categories", 3607 "type category [<sub-command-options>] ") 3608 { 3609 LoadSubCommand ("define", CommandObjectSP (new CommandObjectTypeCategoryDefine (interpreter))); 3610 LoadSubCommand ("enable", CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter))); 3611 LoadSubCommand ("disable", CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter))); 3612 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter))); 3613 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeCategoryList (interpreter))); 3614 } 3615 3616 ~CommandObjectTypeCategory() override = default; 3617 }; 3618 3619 class CommandObjectTypeSummary : public CommandObjectMultiword 3620 { 3621 public: 3622 CommandObjectTypeSummary (CommandInterpreter &interpreter) : 3623 CommandObjectMultiword (interpreter, 3624 "type summary", 3625 "A set of commands for editing variable summary display options", 3626 "type summary [<sub-command-options>] ") 3627 { 3628 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter))); 3629 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter))); 3630 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter))); 3631 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); 3632 LoadSubCommand ("info", CommandObjectSP (new CommandObjectFormatterInfo<TypeSummaryImpl>(interpreter, 3633 "summary", 3634 [](ValueObject& valobj) -> TypeSummaryImpl::SharedPointer { 3635 return valobj.GetSummaryFormat(); 3636 }))); 3637 } 3638 3639 ~CommandObjectTypeSummary() override = default; 3640 }; 3641 3642 //------------------------------------------------------------------------- 3643 // CommandObjectType 3644 //------------------------------------------------------------------------- 3645 3646 CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) : 3647 CommandObjectMultiword (interpreter, 3648 "type", 3649 "A set of commands for operating on the type system", 3650 "type [<sub-command-options>]") 3651 { 3652 LoadSubCommand ("category", CommandObjectSP (new CommandObjectTypeCategory (interpreter))); 3653 LoadSubCommand ("filter", CommandObjectSP (new CommandObjectTypeFilter (interpreter))); 3654 LoadSubCommand ("format", CommandObjectSP (new CommandObjectTypeFormat (interpreter))); 3655 LoadSubCommand ("summary", CommandObjectSP (new CommandObjectTypeSummary (interpreter))); 3656 #ifndef LLDB_DISABLE_PYTHON 3657 LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter))); 3658 #endif // LLDB_DISABLE_PYTHON 3659 LoadSubCommand ("lookup", CommandObjectSP (new CommandObjectTypeLookup (interpreter))); 3660 } 3661 3662 CommandObjectType::~CommandObjectType() = default; 3663