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