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