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