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