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