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