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