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() {} 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() {} 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() {} 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() {} 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 919 ~CommandObjectTypeFormatterClear() override = default; 920 921 protected: 922 virtual void FormatterSpecificDeletion() {} 923 924 bool DoExecute(Args &command, CommandReturnObject &result) override { 925 if (m_options.m_delete_all) { 926 DataVisualization::Categories::ForEach( 927 [this](const TypeCategoryImplSP &category_sp) -> bool { 928 category_sp->Clear(m_formatter_kind_mask); 929 return true; 930 }); 931 } else { 932 lldb::TypeCategoryImplSP category; 933 if (command.GetArgumentCount() > 0) { 934 const char *cat_name = command.GetArgumentAtIndex(0); 935 ConstString cat_nameCS(cat_name); 936 DataVisualization::Categories::GetCategory(cat_nameCS, category); 937 } else { 938 DataVisualization::Categories::GetCategory(ConstString(nullptr), 939 category); 940 } 941 category->Clear(m_formatter_kind_mask); 942 } 943 944 FormatterSpecificDeletion(); 945 946 result.SetStatus(eReturnStatusSuccessFinishResult); 947 return result.Succeeded(); 948 } 949 }; 950 951 // CommandObjectTypeFormatDelete 952 953 class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete { 954 public: 955 CommandObjectTypeFormatDelete(CommandInterpreter &interpreter) 956 : CommandObjectTypeFormatterDelete( 957 interpreter, 958 eFormatCategoryItemValue | eFormatCategoryItemRegexValue, 959 "type format delete", 960 "Delete an existing formatting style for a type.") {} 961 962 ~CommandObjectTypeFormatDelete() override = default; 963 }; 964 965 // CommandObjectTypeFormatClear 966 967 class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear { 968 public: 969 CommandObjectTypeFormatClear(CommandInterpreter &interpreter) 970 : CommandObjectTypeFormatterClear( 971 interpreter, 972 eFormatCategoryItemValue | eFormatCategoryItemRegexValue, 973 "type format clear", "Delete all existing format styles.") {} 974 }; 975 976 #define LLDB_OPTIONS_type_formatter_list 977 #include "CommandOptions.inc" 978 979 template <typename FormatterType> 980 class CommandObjectTypeFormatterList : public CommandObjectParsed { 981 typedef typename FormatterType::SharedPointer FormatterSharedPointer; 982 983 class CommandOptions : public Options { 984 public: 985 CommandOptions() 986 : Options(), m_category_regex("", ""), 987 m_category_language(lldb::eLanguageTypeUnknown, 988 lldb::eLanguageTypeUnknown) {} 989 990 ~CommandOptions() override = default; 991 992 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 993 ExecutionContext *execution_context) override { 994 Status error; 995 const int short_option = m_getopt_table[option_idx].val; 996 switch (short_option) { 997 case 'w': 998 m_category_regex.SetCurrentValue(option_arg); 999 m_category_regex.SetOptionWasSet(); 1000 break; 1001 case 'l': 1002 error = m_category_language.SetValueFromString(option_arg); 1003 if (error.Success()) 1004 m_category_language.SetOptionWasSet(); 1005 break; 1006 default: 1007 llvm_unreachable("Unimplemented option"); 1008 } 1009 1010 return error; 1011 } 1012 1013 void OptionParsingStarting(ExecutionContext *execution_context) override { 1014 m_category_regex.Clear(); 1015 m_category_language.Clear(); 1016 } 1017 1018 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1019 return llvm::makeArrayRef(g_type_formatter_list_options); 1020 } 1021 1022 // Instance variables to hold the values for command options. 1023 1024 OptionValueString m_category_regex; 1025 OptionValueLanguage m_category_language; 1026 }; 1027 1028 CommandOptions m_options; 1029 1030 Options *GetOptions() override { return &m_options; } 1031 1032 public: 1033 CommandObjectTypeFormatterList(CommandInterpreter &interpreter, 1034 const char *name, const char *help) 1035 : CommandObjectParsed(interpreter, name, help, nullptr), m_options() { 1036 CommandArgumentEntry type_arg; 1037 CommandArgumentData type_style_arg; 1038 1039 type_style_arg.arg_type = eArgTypeName; 1040 type_style_arg.arg_repetition = eArgRepeatOptional; 1041 1042 type_arg.push_back(type_style_arg); 1043 1044 m_arguments.push_back(type_arg); 1045 } 1046 1047 ~CommandObjectTypeFormatterList() override = default; 1048 1049 protected: 1050 virtual bool FormatterSpecificList(CommandReturnObject &result) { 1051 return false; 1052 } 1053 1054 bool DoExecute(Args &command, CommandReturnObject &result) override { 1055 const size_t argc = command.GetArgumentCount(); 1056 1057 std::unique_ptr<RegularExpression> category_regex; 1058 std::unique_ptr<RegularExpression> formatter_regex; 1059 1060 if (m_options.m_category_regex.OptionWasSet()) { 1061 category_regex = std::make_unique<RegularExpression>( 1062 m_options.m_category_regex.GetCurrentValueAsRef()); 1063 if (!category_regex->IsValid()) { 1064 result.AppendErrorWithFormat( 1065 "syntax error in category regular expression '%s'", 1066 m_options.m_category_regex.GetCurrentValueAsRef().str().c_str()); 1067 return false; 1068 } 1069 } 1070 1071 if (argc == 1) { 1072 const char *arg = command.GetArgumentAtIndex(0); 1073 formatter_regex = std::make_unique<RegularExpression>(arg); 1074 if (!formatter_regex->IsValid()) { 1075 result.AppendErrorWithFormat("syntax error in regular expression '%s'", 1076 arg); 1077 return false; 1078 } 1079 } 1080 1081 bool any_printed = false; 1082 1083 auto category_closure = 1084 [&result, &formatter_regex, 1085 &any_printed](const lldb::TypeCategoryImplSP &category) -> void { 1086 result.GetOutputStream().Printf( 1087 "-----------------------\nCategory: %s%s\n-----------------------\n", 1088 category->GetName(), category->IsEnabled() ? "" : " (disabled)"); 1089 1090 TypeCategoryImpl::ForEachCallbacks<FormatterType> foreach; 1091 foreach 1092 .SetExact([&result, &formatter_regex, &any_printed]( 1093 const TypeMatcher &type_matcher, 1094 const FormatterSharedPointer &format_sp) -> bool { 1095 if (formatter_regex) { 1096 bool escape = true; 1097 if (type_matcher.CreatedBySameMatchString( 1098 ConstString(formatter_regex->GetText()))) { 1099 escape = false; 1100 } else if (formatter_regex->Execute( 1101 type_matcher.GetMatchString().GetStringRef())) { 1102 escape = false; 1103 } 1104 1105 if (escape) 1106 return true; 1107 } 1108 1109 any_printed = true; 1110 result.GetOutputStream().Printf( 1111 "%s: %s\n", type_matcher.GetMatchString().GetCString(), 1112 format_sp->GetDescription().c_str()); 1113 return true; 1114 }); 1115 1116 foreach 1117 .SetWithRegex([&result, &formatter_regex, &any_printed]( 1118 const TypeMatcher &type_matcher, 1119 const FormatterSharedPointer &format_sp) -> bool { 1120 if (formatter_regex) { 1121 bool escape = true; 1122 if (type_matcher.CreatedBySameMatchString( 1123 ConstString(formatter_regex->GetText()))) { 1124 escape = false; 1125 } else if (formatter_regex->Execute( 1126 type_matcher.GetMatchString().GetStringRef())) { 1127 escape = false; 1128 } 1129 1130 if (escape) 1131 return true; 1132 } 1133 1134 any_printed = true; 1135 result.GetOutputStream().Printf( 1136 "%s: %s\n", type_matcher.GetMatchString().GetCString(), 1137 format_sp->GetDescription().c_str()); 1138 return true; 1139 }); 1140 1141 category->ForEach(foreach); 1142 }; 1143 1144 if (m_options.m_category_language.OptionWasSet()) { 1145 lldb::TypeCategoryImplSP category_sp; 1146 DataVisualization::Categories::GetCategory( 1147 m_options.m_category_language.GetCurrentValue(), category_sp); 1148 if (category_sp) 1149 category_closure(category_sp); 1150 } else { 1151 DataVisualization::Categories::ForEach( 1152 [&category_regex, &category_closure]( 1153 const lldb::TypeCategoryImplSP &category) -> bool { 1154 if (category_regex) { 1155 bool escape = true; 1156 if (category->GetName() == category_regex->GetText()) { 1157 escape = false; 1158 } else if (category_regex->Execute(category->GetName())) { 1159 escape = false; 1160 } 1161 1162 if (escape) 1163 return true; 1164 } 1165 1166 category_closure(category); 1167 1168 return true; 1169 }); 1170 1171 any_printed = FormatterSpecificList(result) | any_printed; 1172 } 1173 1174 if (any_printed) 1175 result.SetStatus(eReturnStatusSuccessFinishResult); 1176 else { 1177 result.GetOutputStream().PutCString("no matching results found.\n"); 1178 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1179 } 1180 return result.Succeeded(); 1181 } 1182 }; 1183 1184 // CommandObjectTypeFormatList 1185 1186 class CommandObjectTypeFormatList 1187 : public CommandObjectTypeFormatterList<TypeFormatImpl> { 1188 public: 1189 CommandObjectTypeFormatList(CommandInterpreter &interpreter) 1190 : CommandObjectTypeFormatterList(interpreter, "type format list", 1191 "Show a list of current formats.") {} 1192 }; 1193 1194 Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue( 1195 uint32_t option_idx, llvm::StringRef option_arg, 1196 ExecutionContext *execution_context) { 1197 Status error; 1198 const int short_option = m_getopt_table[option_idx].val; 1199 bool success; 1200 1201 switch (short_option) { 1202 case 'C': 1203 m_flags.SetCascades(OptionArgParser::ToBoolean(option_arg, true, &success)); 1204 if (!success) 1205 error.SetErrorStringWithFormat("invalid value for cascade: %s", 1206 option_arg.str().c_str()); 1207 break; 1208 case 'e': 1209 m_flags.SetDontShowChildren(false); 1210 break; 1211 case 'h': 1212 m_flags.SetHideEmptyAggregates(true); 1213 break; 1214 case 'v': 1215 m_flags.SetDontShowValue(true); 1216 break; 1217 case 'c': 1218 m_flags.SetShowMembersOneLiner(true); 1219 break; 1220 case 's': 1221 m_format_string = std::string(option_arg); 1222 break; 1223 case 'p': 1224 m_flags.SetSkipPointers(true); 1225 break; 1226 case 'r': 1227 m_flags.SetSkipReferences(true); 1228 break; 1229 case 'x': 1230 m_regex = true; 1231 break; 1232 case 'n': 1233 m_name.SetString(option_arg); 1234 break; 1235 case 'o': 1236 m_python_script = std::string(option_arg); 1237 m_is_add_script = true; 1238 break; 1239 case 'F': 1240 m_python_function = std::string(option_arg); 1241 m_is_add_script = true; 1242 break; 1243 case 'P': 1244 m_is_add_script = true; 1245 break; 1246 case 'w': 1247 m_category = std::string(option_arg); 1248 break; 1249 case 'O': 1250 m_flags.SetHideItemNames(true); 1251 break; 1252 default: 1253 llvm_unreachable("Unimplemented option"); 1254 } 1255 1256 return error; 1257 } 1258 1259 void CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting( 1260 ExecutionContext *execution_context) { 1261 m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false); 1262 m_flags.SetShowMembersOneLiner(false) 1263 .SetSkipPointers(false) 1264 .SetSkipReferences(false) 1265 .SetHideItemNames(false); 1266 1267 m_regex = false; 1268 m_name.Clear(); 1269 m_python_script = ""; 1270 m_python_function = ""; 1271 m_format_string = ""; 1272 m_is_add_script = false; 1273 m_category = "default"; 1274 } 1275 1276 #if LLDB_ENABLE_PYTHON 1277 1278 bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary( 1279 Args &command, CommandReturnObject &result) { 1280 const size_t argc = command.GetArgumentCount(); 1281 1282 if (argc < 1 && !m_options.m_name) { 1283 result.AppendErrorWithFormat("%s takes one or more args.\n", 1284 m_cmd_name.c_str()); 1285 return false; 1286 } 1287 1288 TypeSummaryImplSP script_format; 1289 1290 if (!m_options.m_python_function 1291 .empty()) // we have a Python function ready to use 1292 { 1293 const char *funct_name = m_options.m_python_function.c_str(); 1294 if (!funct_name || !funct_name[0]) { 1295 result.AppendError("function name empty.\n"); 1296 return false; 1297 } 1298 1299 std::string code = 1300 (" " + m_options.m_python_function + "(valobj,internal_dict)"); 1301 1302 script_format = std::make_shared<ScriptSummaryFormat>( 1303 m_options.m_flags, funct_name, code.c_str()); 1304 1305 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 1306 1307 if (interpreter && !interpreter->CheckObjectExists(funct_name)) 1308 result.AppendWarningWithFormat( 1309 "The provided function \"%s\" does not exist - " 1310 "please define it before attempting to use this summary.\n", 1311 funct_name); 1312 } else if (!m_options.m_python_script 1313 .empty()) // we have a quick 1-line script, just use it 1314 { 1315 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 1316 if (!interpreter) { 1317 result.AppendError("script interpreter missing - unable to generate " 1318 "function wrapper.\n"); 1319 return false; 1320 } 1321 StringList funct_sl; 1322 funct_sl << m_options.m_python_script.c_str(); 1323 std::string funct_name_str; 1324 if (!interpreter->GenerateTypeScriptFunction(funct_sl, funct_name_str)) { 1325 result.AppendError("unable to generate function wrapper.\n"); 1326 return false; 1327 } 1328 if (funct_name_str.empty()) { 1329 result.AppendError( 1330 "script interpreter failed to generate a valid function name.\n"); 1331 return false; 1332 } 1333 1334 std::string code = " " + m_options.m_python_script; 1335 1336 script_format = std::make_shared<ScriptSummaryFormat>( 1337 m_options.m_flags, funct_name_str.c_str(), code.c_str()); 1338 } else { 1339 // Use an IOHandler to grab Python code from the user 1340 auto options = std::make_unique<ScriptAddOptions>( 1341 m_options.m_flags, m_options.m_regex, m_options.m_name, 1342 m_options.m_category); 1343 1344 for (auto &entry : command.entries()) { 1345 if (entry.ref().empty()) { 1346 result.AppendError("empty typenames not allowed"); 1347 return false; 1348 } 1349 1350 options->m_target_types << std::string(entry.ref()); 1351 } 1352 1353 m_interpreter.GetPythonCommandsFromIOHandler( 1354 " ", // Prompt 1355 *this, // IOHandlerDelegate 1356 options.release()); // Baton for the "io_handler" that will be passed 1357 // back into our IOHandlerDelegate functions 1358 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1359 1360 return result.Succeeded(); 1361 } 1362 1363 // if I am here, script_format must point to something good, so I can add 1364 // that as a script summary to all interested parties 1365 1366 Status error; 1367 1368 for (auto &entry : command.entries()) { 1369 CommandObjectTypeSummaryAdd::AddSummary( 1370 ConstString(entry.ref()), script_format, 1371 (m_options.m_regex ? eRegexSummary : eRegularSummary), 1372 m_options.m_category, &error); 1373 if (error.Fail()) { 1374 result.AppendError(error.AsCString()); 1375 return false; 1376 } 1377 } 1378 1379 if (m_options.m_name) { 1380 AddSummary(m_options.m_name, script_format, eNamedSummary, 1381 m_options.m_category, &error); 1382 if (error.Fail()) { 1383 result.AppendError(error.AsCString()); 1384 result.AppendError("added to types, but not given a name"); 1385 return false; 1386 } 1387 } 1388 1389 return result.Succeeded(); 1390 } 1391 1392 #endif 1393 1394 bool CommandObjectTypeSummaryAdd::Execute_StringSummary( 1395 Args &command, CommandReturnObject &result) { 1396 const size_t argc = command.GetArgumentCount(); 1397 1398 if (argc < 1 && !m_options.m_name) { 1399 result.AppendErrorWithFormat("%s takes one or more args.\n", 1400 m_cmd_name.c_str()); 1401 return false; 1402 } 1403 1404 if (!m_options.m_flags.GetShowMembersOneLiner() && 1405 m_options.m_format_string.empty()) { 1406 result.AppendError("empty summary strings not allowed"); 1407 return false; 1408 } 1409 1410 const char *format_cstr = (m_options.m_flags.GetShowMembersOneLiner() 1411 ? "" 1412 : m_options.m_format_string.c_str()); 1413 1414 // ${var%S} is an endless recursion, prevent it 1415 if (strcmp(format_cstr, "${var%S}") == 0) { 1416 result.AppendError("recursive summary not allowed"); 1417 return false; 1418 } 1419 1420 std::unique_ptr<StringSummaryFormat> string_format( 1421 new StringSummaryFormat(m_options.m_flags, format_cstr)); 1422 if (!string_format) { 1423 result.AppendError("summary creation failed"); 1424 return false; 1425 } 1426 if (string_format->m_error.Fail()) { 1427 result.AppendErrorWithFormat("syntax error: %s", 1428 string_format->m_error.AsCString("<unknown>")); 1429 return false; 1430 } 1431 lldb::TypeSummaryImplSP entry(string_format.release()); 1432 1433 // now I have a valid format, let's add it to every type 1434 Status error; 1435 for (auto &arg_entry : command.entries()) { 1436 if (arg_entry.ref().empty()) { 1437 result.AppendError("empty typenames not allowed"); 1438 return false; 1439 } 1440 ConstString typeCS(arg_entry.ref()); 1441 1442 AddSummary(typeCS, entry, 1443 (m_options.m_regex ? eRegexSummary : eRegularSummary), 1444 m_options.m_category, &error); 1445 1446 if (error.Fail()) { 1447 result.AppendError(error.AsCString()); 1448 return false; 1449 } 1450 } 1451 1452 if (m_options.m_name) { 1453 AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category, 1454 &error); 1455 if (error.Fail()) { 1456 result.AppendError(error.AsCString()); 1457 result.AppendError("added to types, but not given a name"); 1458 return false; 1459 } 1460 } 1461 1462 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1463 return result.Succeeded(); 1464 } 1465 1466 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd( 1467 CommandInterpreter &interpreter) 1468 : CommandObjectParsed(interpreter, "type summary add", 1469 "Add a new summary style for a type.", nullptr), 1470 IOHandlerDelegateMultiline("DONE"), m_options(interpreter) { 1471 CommandArgumentEntry type_arg; 1472 CommandArgumentData type_style_arg; 1473 1474 type_style_arg.arg_type = eArgTypeName; 1475 type_style_arg.arg_repetition = eArgRepeatPlus; 1476 1477 type_arg.push_back(type_style_arg); 1478 1479 m_arguments.push_back(type_arg); 1480 1481 SetHelpLong( 1482 R"( 1483 The following examples of 'type summary add' refer to this code snippet for context: 1484 1485 struct JustADemo 1486 { 1487 int* ptr; 1488 float value; 1489 JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {} 1490 }; 1491 JustADemo demo_instance(42, 3.14); 1492 1493 typedef JustADemo NewDemo; 1494 NewDemo new_demo_instance(42, 3.14); 1495 1496 (lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo 1497 1498 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42" 1499 1500 (lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo 1501 1502 Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14" 1503 1504 )" 1505 "Alternatively, you could define formatting for all pointers to integers and \ 1506 rely on that when formatting JustADemo to obtain the same result:" 1507 R"( 1508 1509 (lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *" 1510 (lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo 1511 1512 )" 1513 "Type summaries are automatically applied to derived typedefs, so the examples \ 1514 above apply to both JustADemo and NewDemo. The cascade option can be used to \ 1515 suppress this behavior:" 1516 R"( 1517 1518 (lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no 1519 1520 The summary will now be used for values of JustADemo but not NewDemo. 1521 1522 )" 1523 "By default summaries are shown for pointers and references to values of the \ 1524 specified type. To suppress formatting for pointers use the -p option, or apply \ 1525 the corresponding -r option to suppress formatting for references:" 1526 R"( 1527 1528 (lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo 1529 1530 )" 1531 "One-line summaries including all fields in a type can be inferred without supplying an \ 1532 explicit summary string by passing the -c option:" 1533 R"( 1534 1535 (lldb) type summary add -c JustADemo 1536 (lldb) frame variable demo_instance 1537 (ptr=<address>, value=3.14) 1538 1539 )" 1540 "Type summaries normally suppress the nested display of individual fields. To \ 1541 supply a summary to supplement the default structure add the -e option:" 1542 R"( 1543 1544 (lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo 1545 1546 )" 1547 "Now when displaying JustADemo values the int* is displayed, followed by the \ 1548 standard LLDB sequence of children, one per line:" 1549 R"( 1550 1551 *ptr = 42 { 1552 ptr = <address> 1553 value = 3.14 1554 } 1555 1556 )" 1557 "You can also add summaries written in Python. These scripts use lldb public API to \ 1558 gather information from your variables and produce a meaningful summary. To start a \ 1559 multi-line script use the -P option. The function declaration will be displayed along with \ 1560 a comment describing the two arguments. End your script with the word 'DONE' on a line by \ 1561 itself:" 1562 R"( 1563 1564 (lldb) type summary add JustADemo -P 1565 def function (valobj,internal_dict): 1566 """valobj: an SBValue which you want to provide a summary for 1567 internal_dict: an LLDB support object not to be used""" 1568 value = valobj.GetChildMemberWithName('value'); 1569 return 'My value is ' + value.GetValue(); 1570 DONE 1571 1572 Alternatively, the -o option can be used when providing a simple one-line Python script: 1573 1574 (lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")"); 1575 } 1576 1577 bool CommandObjectTypeSummaryAdd::DoExecute(Args &command, 1578 CommandReturnObject &result) { 1579 WarnOnPotentialUnquotedUnsignedType(command, result); 1580 1581 if (m_options.m_is_add_script) { 1582 #if LLDB_ENABLE_PYTHON 1583 return Execute_ScriptSummary(command, result); 1584 #else 1585 result.AppendError("python is disabled"); 1586 return false; 1587 #endif 1588 } 1589 1590 return Execute_StringSummary(command, result); 1591 } 1592 1593 static bool FixArrayTypeNameWithRegex(ConstString &type_name) { 1594 llvm::StringRef type_name_ref(type_name.GetStringRef()); 1595 1596 if (type_name_ref.endswith("[]")) { 1597 std::string type_name_str(type_name.GetCString()); 1598 type_name_str.resize(type_name_str.length() - 2); 1599 if (type_name_str.back() != ' ') 1600 type_name_str.append(" ?\\[[0-9]+\\]"); 1601 else 1602 type_name_str.append("\\[[0-9]+\\]"); 1603 type_name.SetCString(type_name_str.c_str()); 1604 return true; 1605 } 1606 return false; 1607 } 1608 1609 bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, 1610 TypeSummaryImplSP entry, 1611 SummaryFormatType type, 1612 std::string category_name, 1613 Status *error) { 1614 lldb::TypeCategoryImplSP category; 1615 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), 1616 category); 1617 1618 if (type == eRegularSummary) { 1619 if (FixArrayTypeNameWithRegex(type_name)) 1620 type = eRegexSummary; 1621 } 1622 1623 if (type == eRegexSummary) { 1624 RegularExpression typeRX(type_name.GetStringRef()); 1625 if (!typeRX.IsValid()) { 1626 if (error) 1627 error->SetErrorString( 1628 "regex format error (maybe this is not really a regex?)"); 1629 return false; 1630 } 1631 1632 category->GetRegexTypeSummariesContainer()->Delete(type_name); 1633 category->GetRegexTypeSummariesContainer()->Add(std::move(typeRX), entry); 1634 1635 return true; 1636 } else if (type == eNamedSummary) { 1637 // system named summaries do not exist (yet?) 1638 DataVisualization::NamedSummaryFormats::Add(type_name, entry); 1639 return true; 1640 } else { 1641 category->GetTypeSummariesContainer()->Add(std::move(type_name), entry); 1642 return true; 1643 } 1644 } 1645 1646 // CommandObjectTypeSummaryDelete 1647 1648 class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete { 1649 public: 1650 CommandObjectTypeSummaryDelete(CommandInterpreter &interpreter) 1651 : CommandObjectTypeFormatterDelete( 1652 interpreter, 1653 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, 1654 "type summary delete", "Delete an existing summary for a type.") {} 1655 1656 ~CommandObjectTypeSummaryDelete() override = default; 1657 1658 protected: 1659 bool FormatterSpecificDeletion(ConstString typeCS) override { 1660 if (m_options.m_language != lldb::eLanguageTypeUnknown) 1661 return false; 1662 return DataVisualization::NamedSummaryFormats::Delete(typeCS); 1663 } 1664 }; 1665 1666 class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear { 1667 public: 1668 CommandObjectTypeSummaryClear(CommandInterpreter &interpreter) 1669 : CommandObjectTypeFormatterClear( 1670 interpreter, 1671 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, 1672 "type summary clear", "Delete all existing summaries.") {} 1673 1674 protected: 1675 void FormatterSpecificDeletion() override { 1676 DataVisualization::NamedSummaryFormats::Clear(); 1677 } 1678 }; 1679 1680 // CommandObjectTypeSummaryList 1681 1682 class CommandObjectTypeSummaryList 1683 : public CommandObjectTypeFormatterList<TypeSummaryImpl> { 1684 public: 1685 CommandObjectTypeSummaryList(CommandInterpreter &interpreter) 1686 : CommandObjectTypeFormatterList(interpreter, "type summary list", 1687 "Show a list of current summaries.") {} 1688 1689 protected: 1690 bool FormatterSpecificList(CommandReturnObject &result) override { 1691 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) { 1692 result.GetOutputStream().Printf("Named summaries:\n"); 1693 DataVisualization::NamedSummaryFormats::ForEach( 1694 [&result](const TypeMatcher &type_matcher, 1695 const TypeSummaryImplSP &summary_sp) -> bool { 1696 result.GetOutputStream().Printf( 1697 "%s: %s\n", type_matcher.GetMatchString().GetCString(), 1698 summary_sp->GetDescription().c_str()); 1699 return true; 1700 }); 1701 return true; 1702 } 1703 return false; 1704 } 1705 }; 1706 1707 // CommandObjectTypeCategoryDefine 1708 #define LLDB_OPTIONS_type_category_define 1709 #include "CommandOptions.inc" 1710 1711 class CommandObjectTypeCategoryDefine : public CommandObjectParsed { 1712 class CommandOptions : public Options { 1713 public: 1714 CommandOptions() 1715 : m_define_enabled(false, false), 1716 m_cate_language(eLanguageTypeUnknown, eLanguageTypeUnknown) {} 1717 1718 ~CommandOptions() override = default; 1719 1720 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1721 ExecutionContext *execution_context) override { 1722 Status error; 1723 const int short_option = m_getopt_table[option_idx].val; 1724 1725 switch (short_option) { 1726 case 'e': 1727 m_define_enabled.SetValueFromString(llvm::StringRef("true")); 1728 break; 1729 case 'l': 1730 error = m_cate_language.SetValueFromString(option_arg); 1731 break; 1732 default: 1733 llvm_unreachable("Unimplemented option"); 1734 } 1735 1736 return error; 1737 } 1738 1739 void OptionParsingStarting(ExecutionContext *execution_context) override { 1740 m_define_enabled.Clear(); 1741 m_cate_language.Clear(); 1742 } 1743 1744 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1745 return llvm::makeArrayRef(g_type_category_define_options); 1746 } 1747 1748 // Instance variables to hold the values for command options. 1749 1750 OptionValueBoolean m_define_enabled; 1751 OptionValueLanguage m_cate_language; 1752 }; 1753 1754 CommandOptions m_options; 1755 1756 Options *GetOptions() override { return &m_options; } 1757 1758 public: 1759 CommandObjectTypeCategoryDefine(CommandInterpreter &interpreter) 1760 : CommandObjectParsed(interpreter, "type category define", 1761 "Define a new category as a source of formatters.", 1762 nullptr) { 1763 CommandArgumentEntry type_arg; 1764 CommandArgumentData type_style_arg; 1765 1766 type_style_arg.arg_type = eArgTypeName; 1767 type_style_arg.arg_repetition = eArgRepeatPlus; 1768 1769 type_arg.push_back(type_style_arg); 1770 1771 m_arguments.push_back(type_arg); 1772 } 1773 1774 ~CommandObjectTypeCategoryDefine() override = default; 1775 1776 void 1777 HandleArgumentCompletion(CompletionRequest &request, 1778 OptionElementVector &opt_element_vector) override { 1779 CommandCompletions::InvokeCommonCompletionCallbacks( 1780 GetCommandInterpreter(), 1781 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 1782 } 1783 1784 protected: 1785 bool DoExecute(Args &command, CommandReturnObject &result) override { 1786 const size_t argc = command.GetArgumentCount(); 1787 1788 if (argc < 1) { 1789 result.AppendErrorWithFormat("%s takes 1 or more args.\n", 1790 m_cmd_name.c_str()); 1791 return false; 1792 } 1793 1794 for (auto &entry : command.entries()) { 1795 TypeCategoryImplSP category_sp; 1796 if (DataVisualization::Categories::GetCategory(ConstString(entry.ref()), 1797 category_sp) && 1798 category_sp) { 1799 category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue()); 1800 if (m_options.m_define_enabled.GetCurrentValue()) 1801 DataVisualization::Categories::Enable(category_sp, 1802 TypeCategoryMap::Default); 1803 } 1804 } 1805 1806 result.SetStatus(eReturnStatusSuccessFinishResult); 1807 return result.Succeeded(); 1808 } 1809 }; 1810 1811 // CommandObjectTypeCategoryEnable 1812 #define LLDB_OPTIONS_type_category_enable 1813 #include "CommandOptions.inc" 1814 1815 class CommandObjectTypeCategoryEnable : public CommandObjectParsed { 1816 class CommandOptions : public Options { 1817 public: 1818 CommandOptions() {} 1819 1820 ~CommandOptions() override = default; 1821 1822 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1823 ExecutionContext *execution_context) override { 1824 Status error; 1825 const int short_option = m_getopt_table[option_idx].val; 1826 1827 switch (short_option) { 1828 case 'l': 1829 if (!option_arg.empty()) { 1830 m_language = Language::GetLanguageTypeFromString(option_arg); 1831 if (m_language == lldb::eLanguageTypeUnknown) 1832 error.SetErrorStringWithFormat("unrecognized language '%s'", 1833 option_arg.str().c_str()); 1834 } 1835 break; 1836 default: 1837 llvm_unreachable("Unimplemented option"); 1838 } 1839 1840 return error; 1841 } 1842 1843 void OptionParsingStarting(ExecutionContext *execution_context) override { 1844 m_language = lldb::eLanguageTypeUnknown; 1845 } 1846 1847 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1848 return llvm::makeArrayRef(g_type_category_enable_options); 1849 } 1850 1851 // Instance variables to hold the values for command options. 1852 1853 lldb::LanguageType m_language; 1854 }; 1855 1856 CommandOptions m_options; 1857 1858 Options *GetOptions() override { return &m_options; } 1859 1860 public: 1861 CommandObjectTypeCategoryEnable(CommandInterpreter &interpreter) 1862 : CommandObjectParsed(interpreter, "type category enable", 1863 "Enable a category as a source of formatters.", 1864 nullptr) { 1865 CommandArgumentEntry type_arg; 1866 CommandArgumentData type_style_arg; 1867 1868 type_style_arg.arg_type = eArgTypeName; 1869 type_style_arg.arg_repetition = eArgRepeatPlus; 1870 1871 type_arg.push_back(type_style_arg); 1872 1873 m_arguments.push_back(type_arg); 1874 } 1875 1876 ~CommandObjectTypeCategoryEnable() override = default; 1877 1878 void 1879 HandleArgumentCompletion(CompletionRequest &request, 1880 OptionElementVector &opt_element_vector) override { 1881 CommandCompletions::InvokeCommonCompletionCallbacks( 1882 GetCommandInterpreter(), 1883 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 1884 } 1885 1886 protected: 1887 bool DoExecute(Args &command, CommandReturnObject &result) override { 1888 const size_t argc = command.GetArgumentCount(); 1889 1890 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) { 1891 result.AppendErrorWithFormat("%s takes arguments and/or a language", 1892 m_cmd_name.c_str()); 1893 return false; 1894 } 1895 1896 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) { 1897 DataVisualization::Categories::EnableStar(); 1898 } else if (argc > 0) { 1899 for (int i = argc - 1; i >= 0; i--) { 1900 const char *typeA = command.GetArgumentAtIndex(i); 1901 ConstString typeCS(typeA); 1902 1903 if (!typeCS) { 1904 result.AppendError("empty category name not allowed"); 1905 return false; 1906 } 1907 DataVisualization::Categories::Enable(typeCS); 1908 lldb::TypeCategoryImplSP cate; 1909 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate) { 1910 if (cate->GetCount() == 0) { 1911 result.AppendWarning("empty category enabled (typo?)"); 1912 } 1913 } 1914 } 1915 } 1916 1917 if (m_options.m_language != lldb::eLanguageTypeUnknown) 1918 DataVisualization::Categories::Enable(m_options.m_language); 1919 1920 result.SetStatus(eReturnStatusSuccessFinishResult); 1921 return result.Succeeded(); 1922 } 1923 }; 1924 1925 // CommandObjectTypeCategoryDelete 1926 1927 class CommandObjectTypeCategoryDelete : public CommandObjectParsed { 1928 public: 1929 CommandObjectTypeCategoryDelete(CommandInterpreter &interpreter) 1930 : CommandObjectParsed(interpreter, "type category delete", 1931 "Delete a category and all associated formatters.", 1932 nullptr) { 1933 CommandArgumentEntry type_arg; 1934 CommandArgumentData type_style_arg; 1935 1936 type_style_arg.arg_type = eArgTypeName; 1937 type_style_arg.arg_repetition = eArgRepeatPlus; 1938 1939 type_arg.push_back(type_style_arg); 1940 1941 m_arguments.push_back(type_arg); 1942 } 1943 1944 ~CommandObjectTypeCategoryDelete() override = default; 1945 1946 void 1947 HandleArgumentCompletion(CompletionRequest &request, 1948 OptionElementVector &opt_element_vector) override { 1949 CommandCompletions::InvokeCommonCompletionCallbacks( 1950 GetCommandInterpreter(), 1951 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 1952 } 1953 1954 protected: 1955 bool DoExecute(Args &command, CommandReturnObject &result) override { 1956 const size_t argc = command.GetArgumentCount(); 1957 1958 if (argc < 1) { 1959 result.AppendErrorWithFormat("%s takes 1 or more arg.\n", 1960 m_cmd_name.c_str()); 1961 return false; 1962 } 1963 1964 bool success = true; 1965 1966 // the order is not relevant here 1967 for (int i = argc - 1; i >= 0; i--) { 1968 const char *typeA = command.GetArgumentAtIndex(i); 1969 ConstString typeCS(typeA); 1970 1971 if (!typeCS) { 1972 result.AppendError("empty category name not allowed"); 1973 return false; 1974 } 1975 if (!DataVisualization::Categories::Delete(typeCS)) 1976 success = false; // keep deleting even if we hit an error 1977 } 1978 if (success) { 1979 result.SetStatus(eReturnStatusSuccessFinishResult); 1980 return result.Succeeded(); 1981 } else { 1982 result.AppendError("cannot delete one or more categories\n"); 1983 return false; 1984 } 1985 } 1986 }; 1987 1988 // CommandObjectTypeCategoryDisable 1989 #define LLDB_OPTIONS_type_category_disable 1990 #include "CommandOptions.inc" 1991 1992 class CommandObjectTypeCategoryDisable : public CommandObjectParsed { 1993 class CommandOptions : public Options { 1994 public: 1995 CommandOptions() {} 1996 1997 ~CommandOptions() override = default; 1998 1999 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2000 ExecutionContext *execution_context) override { 2001 Status error; 2002 const int short_option = m_getopt_table[option_idx].val; 2003 2004 switch (short_option) { 2005 case 'l': 2006 if (!option_arg.empty()) { 2007 m_language = Language::GetLanguageTypeFromString(option_arg); 2008 if (m_language == lldb::eLanguageTypeUnknown) 2009 error.SetErrorStringWithFormat("unrecognized language '%s'", 2010 option_arg.str().c_str()); 2011 } 2012 break; 2013 default: 2014 llvm_unreachable("Unimplemented option"); 2015 } 2016 2017 return error; 2018 } 2019 2020 void OptionParsingStarting(ExecutionContext *execution_context) override { 2021 m_language = lldb::eLanguageTypeUnknown; 2022 } 2023 2024 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2025 return llvm::makeArrayRef(g_type_category_disable_options); 2026 } 2027 2028 // Instance variables to hold the values for command options. 2029 2030 lldb::LanguageType m_language; 2031 }; 2032 2033 CommandOptions m_options; 2034 2035 Options *GetOptions() override { return &m_options; } 2036 2037 public: 2038 CommandObjectTypeCategoryDisable(CommandInterpreter &interpreter) 2039 : CommandObjectParsed(interpreter, "type category disable", 2040 "Disable a category as a source of formatters.", 2041 nullptr) { 2042 CommandArgumentEntry type_arg; 2043 CommandArgumentData type_style_arg; 2044 2045 type_style_arg.arg_type = eArgTypeName; 2046 type_style_arg.arg_repetition = eArgRepeatPlus; 2047 2048 type_arg.push_back(type_style_arg); 2049 2050 m_arguments.push_back(type_arg); 2051 } 2052 2053 ~CommandObjectTypeCategoryDisable() override = default; 2054 2055 void 2056 HandleArgumentCompletion(CompletionRequest &request, 2057 OptionElementVector &opt_element_vector) override { 2058 CommandCompletions::InvokeCommonCompletionCallbacks( 2059 GetCommandInterpreter(), 2060 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 2061 } 2062 2063 protected: 2064 bool DoExecute(Args &command, CommandReturnObject &result) override { 2065 const size_t argc = command.GetArgumentCount(); 2066 2067 if (argc < 1 && m_options.m_language == lldb::eLanguageTypeUnknown) { 2068 result.AppendErrorWithFormat("%s takes arguments and/or a language", 2069 m_cmd_name.c_str()); 2070 return false; 2071 } 2072 2073 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0), "*") == 0) { 2074 DataVisualization::Categories::DisableStar(); 2075 } else if (argc > 0) { 2076 // the order is not relevant here 2077 for (int i = argc - 1; i >= 0; i--) { 2078 const char *typeA = command.GetArgumentAtIndex(i); 2079 ConstString typeCS(typeA); 2080 2081 if (!typeCS) { 2082 result.AppendError("empty category name not allowed"); 2083 return false; 2084 } 2085 DataVisualization::Categories::Disable(typeCS); 2086 } 2087 } 2088 2089 if (m_options.m_language != lldb::eLanguageTypeUnknown) 2090 DataVisualization::Categories::Disable(m_options.m_language); 2091 2092 result.SetStatus(eReturnStatusSuccessFinishResult); 2093 return result.Succeeded(); 2094 } 2095 }; 2096 2097 // CommandObjectTypeCategoryList 2098 2099 class CommandObjectTypeCategoryList : public CommandObjectParsed { 2100 public: 2101 CommandObjectTypeCategoryList(CommandInterpreter &interpreter) 2102 : CommandObjectParsed(interpreter, "type category list", 2103 "Provide a list of all existing categories.", 2104 nullptr) { 2105 CommandArgumentEntry type_arg; 2106 CommandArgumentData type_style_arg; 2107 2108 type_style_arg.arg_type = eArgTypeName; 2109 type_style_arg.arg_repetition = eArgRepeatOptional; 2110 2111 type_arg.push_back(type_style_arg); 2112 2113 m_arguments.push_back(type_arg); 2114 } 2115 2116 ~CommandObjectTypeCategoryList() override = default; 2117 2118 void 2119 HandleArgumentCompletion(CompletionRequest &request, 2120 OptionElementVector &opt_element_vector) override { 2121 if (request.GetCursorIndex()) 2122 return; 2123 CommandCompletions::InvokeCommonCompletionCallbacks( 2124 GetCommandInterpreter(), 2125 CommandCompletions::eTypeCategoryNameCompletion, request, nullptr); 2126 } 2127 2128 protected: 2129 bool DoExecute(Args &command, CommandReturnObject &result) override { 2130 const size_t argc = command.GetArgumentCount(); 2131 2132 std::unique_ptr<RegularExpression> regex; 2133 2134 if (argc == 1) { 2135 const char *arg = command.GetArgumentAtIndex(0); 2136 regex = std::make_unique<RegularExpression>(arg); 2137 if (!regex->IsValid()) { 2138 result.AppendErrorWithFormat( 2139 "syntax error in category regular expression '%s'", arg); 2140 return false; 2141 } 2142 } else if (argc != 0) { 2143 result.AppendErrorWithFormat("%s takes 0 or one arg.\n", 2144 m_cmd_name.c_str()); 2145 return false; 2146 } 2147 2148 DataVisualization::Categories::ForEach( 2149 [®ex, &result](const lldb::TypeCategoryImplSP &category_sp) -> bool { 2150 if (regex) { 2151 bool escape = true; 2152 if (regex->GetText() == category_sp->GetName()) { 2153 escape = false; 2154 } else if (regex->Execute(category_sp->GetName())) { 2155 escape = false; 2156 } 2157 2158 if (escape) 2159 return true; 2160 } 2161 2162 result.GetOutputStream().Printf( 2163 "Category: %s\n", category_sp->GetDescription().c_str()); 2164 2165 return true; 2166 }); 2167 2168 result.SetStatus(eReturnStatusSuccessFinishResult); 2169 return result.Succeeded(); 2170 } 2171 }; 2172 2173 // CommandObjectTypeFilterList 2174 2175 class CommandObjectTypeFilterList 2176 : public CommandObjectTypeFormatterList<TypeFilterImpl> { 2177 public: 2178 CommandObjectTypeFilterList(CommandInterpreter &interpreter) 2179 : CommandObjectTypeFormatterList(interpreter, "type filter list", 2180 "Show a list of current filters.") {} 2181 }; 2182 2183 #if LLDB_ENABLE_PYTHON 2184 2185 // CommandObjectTypeSynthList 2186 2187 class CommandObjectTypeSynthList 2188 : public CommandObjectTypeFormatterList<SyntheticChildren> { 2189 public: 2190 CommandObjectTypeSynthList(CommandInterpreter &interpreter) 2191 : CommandObjectTypeFormatterList( 2192 interpreter, "type synthetic list", 2193 "Show a list of current synthetic providers.") {} 2194 }; 2195 2196 #endif 2197 2198 // CommandObjectTypeFilterDelete 2199 2200 class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete { 2201 public: 2202 CommandObjectTypeFilterDelete(CommandInterpreter &interpreter) 2203 : CommandObjectTypeFormatterDelete( 2204 interpreter, 2205 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2206 "type filter delete", "Delete an existing filter for a type.") {} 2207 2208 ~CommandObjectTypeFilterDelete() override = default; 2209 }; 2210 2211 #if LLDB_ENABLE_PYTHON 2212 2213 // CommandObjectTypeSynthDelete 2214 2215 class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete { 2216 public: 2217 CommandObjectTypeSynthDelete(CommandInterpreter &interpreter) 2218 : CommandObjectTypeFormatterDelete( 2219 interpreter, 2220 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 2221 "type synthetic delete", 2222 "Delete an existing synthetic provider for a type.") {} 2223 2224 ~CommandObjectTypeSynthDelete() override = default; 2225 }; 2226 2227 #endif 2228 2229 // CommandObjectTypeFilterClear 2230 2231 class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear { 2232 public: 2233 CommandObjectTypeFilterClear(CommandInterpreter &interpreter) 2234 : CommandObjectTypeFormatterClear( 2235 interpreter, 2236 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2237 "type filter clear", "Delete all existing filter.") {} 2238 }; 2239 2240 #if LLDB_ENABLE_PYTHON 2241 // CommandObjectTypeSynthClear 2242 2243 class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear { 2244 public: 2245 CommandObjectTypeSynthClear(CommandInterpreter &interpreter) 2246 : CommandObjectTypeFormatterClear( 2247 interpreter, 2248 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 2249 "type synthetic clear", 2250 "Delete all existing synthetic providers.") {} 2251 }; 2252 2253 bool CommandObjectTypeSynthAdd::Execute_HandwritePython( 2254 Args &command, CommandReturnObject &result) { 2255 auto options = std::make_unique<SynthAddOptions>( 2256 m_options.m_skip_pointers, m_options.m_skip_references, 2257 m_options.m_cascade, m_options.m_regex, m_options.m_category); 2258 2259 for (auto &entry : command.entries()) { 2260 if (entry.ref().empty()) { 2261 result.AppendError("empty typenames not allowed"); 2262 return false; 2263 } 2264 2265 options->m_target_types << std::string(entry.ref()); 2266 } 2267 2268 m_interpreter.GetPythonCommandsFromIOHandler( 2269 " ", // Prompt 2270 *this, // IOHandlerDelegate 2271 options.release()); // Baton for the "io_handler" that will be passed back 2272 // into our IOHandlerDelegate functions 2273 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2274 return result.Succeeded(); 2275 } 2276 2277 bool CommandObjectTypeSynthAdd::Execute_PythonClass( 2278 Args &command, CommandReturnObject &result) { 2279 const size_t argc = command.GetArgumentCount(); 2280 2281 if (argc < 1) { 2282 result.AppendErrorWithFormat("%s takes one or more args.\n", 2283 m_cmd_name.c_str()); 2284 return false; 2285 } 2286 2287 if (m_options.m_class_name.empty() && !m_options.m_input_python) { 2288 result.AppendErrorWithFormat("%s needs either a Python class name or -P to " 2289 "directly input Python code.\n", 2290 m_cmd_name.c_str()); 2291 return false; 2292 } 2293 2294 SyntheticChildrenSP entry; 2295 2296 ScriptedSyntheticChildren *impl = new ScriptedSyntheticChildren( 2297 SyntheticChildren::Flags() 2298 .SetCascades(m_options.m_cascade) 2299 .SetSkipPointers(m_options.m_skip_pointers) 2300 .SetSkipReferences(m_options.m_skip_references), 2301 m_options.m_class_name.c_str()); 2302 2303 entry.reset(impl); 2304 2305 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 2306 2307 if (interpreter && 2308 !interpreter->CheckObjectExists(impl->GetPythonClassName())) 2309 result.AppendWarning("The provided class does not exist - please define it " 2310 "before attempting to use this synthetic provider"); 2311 2312 // now I have a valid provider, let's add it to every type 2313 2314 lldb::TypeCategoryImplSP category; 2315 DataVisualization::Categories::GetCategory( 2316 ConstString(m_options.m_category.c_str()), category); 2317 2318 Status error; 2319 2320 for (auto &arg_entry : command.entries()) { 2321 if (arg_entry.ref().empty()) { 2322 result.AppendError("empty typenames not allowed"); 2323 return false; 2324 } 2325 2326 ConstString typeCS(arg_entry.ref()); 2327 if (!AddSynth(typeCS, entry, 2328 m_options.m_regex ? eRegexSynth : eRegularSynth, 2329 m_options.m_category, &error)) { 2330 result.AppendError(error.AsCString()); 2331 return false; 2332 } 2333 } 2334 2335 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2336 return result.Succeeded(); 2337 } 2338 2339 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd( 2340 CommandInterpreter &interpreter) 2341 : CommandObjectParsed(interpreter, "type synthetic add", 2342 "Add a new synthetic provider for a type.", nullptr), 2343 IOHandlerDelegateMultiline("DONE"), m_options() { 2344 CommandArgumentEntry type_arg; 2345 CommandArgumentData type_style_arg; 2346 2347 type_style_arg.arg_type = eArgTypeName; 2348 type_style_arg.arg_repetition = eArgRepeatPlus; 2349 2350 type_arg.push_back(type_style_arg); 2351 2352 m_arguments.push_back(type_arg); 2353 } 2354 2355 bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, 2356 SyntheticChildrenSP entry, 2357 SynthFormatType type, 2358 std::string category_name, 2359 Status *error) { 2360 lldb::TypeCategoryImplSP category; 2361 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), 2362 category); 2363 2364 if (type == eRegularSynth) { 2365 if (FixArrayTypeNameWithRegex(type_name)) 2366 type = eRegexSynth; 2367 } 2368 2369 if (category->AnyMatches( 2370 type_name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 2371 false)) { 2372 if (error) 2373 error->SetErrorStringWithFormat("cannot add synthetic for type %s when " 2374 "filter is defined in same category!", 2375 type_name.AsCString()); 2376 return false; 2377 } 2378 2379 if (type == eRegexSynth) { 2380 RegularExpression typeRX(type_name.GetStringRef()); 2381 if (!typeRX.IsValid()) { 2382 if (error) 2383 error->SetErrorString( 2384 "regex format error (maybe this is not really a regex?)"); 2385 return false; 2386 } 2387 2388 category->GetRegexTypeSyntheticsContainer()->Delete(type_name); 2389 category->GetRegexTypeSyntheticsContainer()->Add(std::move(typeRX), entry); 2390 2391 return true; 2392 } else { 2393 category->GetTypeSyntheticsContainer()->Add(std::move(type_name), entry); 2394 return true; 2395 } 2396 } 2397 2398 #endif 2399 #define LLDB_OPTIONS_type_filter_add 2400 #include "CommandOptions.inc" 2401 2402 class CommandObjectTypeFilterAdd : public CommandObjectParsed { 2403 private: 2404 class CommandOptions : public Options { 2405 typedef std::vector<std::string> option_vector; 2406 2407 public: 2408 CommandOptions() {} 2409 2410 ~CommandOptions() override = default; 2411 2412 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2413 ExecutionContext *execution_context) override { 2414 Status error; 2415 const int short_option = m_getopt_table[option_idx].val; 2416 bool success; 2417 2418 switch (short_option) { 2419 case 'C': 2420 m_cascade = OptionArgParser::ToBoolean(option_arg, true, &success); 2421 if (!success) 2422 error.SetErrorStringWithFormat("invalid value for cascade: %s", 2423 option_arg.str().c_str()); 2424 break; 2425 case 'c': 2426 m_expr_paths.push_back(std::string(option_arg)); 2427 has_child_list = true; 2428 break; 2429 case 'p': 2430 m_skip_pointers = true; 2431 break; 2432 case 'r': 2433 m_skip_references = true; 2434 break; 2435 case 'w': 2436 m_category = std::string(option_arg); 2437 break; 2438 case 'x': 2439 m_regex = true; 2440 break; 2441 default: 2442 llvm_unreachable("Unimplemented option"); 2443 } 2444 2445 return error; 2446 } 2447 2448 void OptionParsingStarting(ExecutionContext *execution_context) override { 2449 m_cascade = true; 2450 m_skip_pointers = false; 2451 m_skip_references = false; 2452 m_category = "default"; 2453 m_expr_paths.clear(); 2454 has_child_list = false; 2455 m_regex = false; 2456 } 2457 2458 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2459 return llvm::makeArrayRef(g_type_filter_add_options); 2460 } 2461 2462 // Instance variables to hold the values for command options. 2463 2464 bool m_cascade; 2465 bool m_skip_references; 2466 bool m_skip_pointers; 2467 bool m_input_python; 2468 option_vector m_expr_paths; 2469 std::string m_category; 2470 bool has_child_list; 2471 bool m_regex; 2472 2473 typedef option_vector::iterator ExpressionPathsIterator; 2474 }; 2475 2476 CommandOptions m_options; 2477 2478 Options *GetOptions() override { return &m_options; } 2479 2480 enum FilterFormatType { eRegularFilter, eRegexFilter }; 2481 2482 bool AddFilter(ConstString type_name, TypeFilterImplSP entry, 2483 FilterFormatType type, std::string category_name, 2484 Status *error) { 2485 lldb::TypeCategoryImplSP category; 2486 DataVisualization::Categories::GetCategory( 2487 ConstString(category_name.c_str()), category); 2488 2489 if (type == eRegularFilter) { 2490 if (FixArrayTypeNameWithRegex(type_name)) 2491 type = eRegexFilter; 2492 } 2493 2494 if (category->AnyMatches( 2495 type_name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 2496 false)) { 2497 if (error) 2498 error->SetErrorStringWithFormat("cannot add filter for type %s when " 2499 "synthetic is defined in same " 2500 "category!", 2501 type_name.AsCString()); 2502 return false; 2503 } 2504 2505 if (type == eRegexFilter) { 2506 RegularExpression typeRX(type_name.GetStringRef()); 2507 if (!typeRX.IsValid()) { 2508 if (error) 2509 error->SetErrorString( 2510 "regex format error (maybe this is not really a regex?)"); 2511 return false; 2512 } 2513 2514 category->GetRegexTypeFiltersContainer()->Delete(type_name); 2515 category->GetRegexTypeFiltersContainer()->Add(std::move(typeRX), entry); 2516 2517 return true; 2518 } else { 2519 category->GetTypeFiltersContainer()->Add(std::move(type_name), entry); 2520 return true; 2521 } 2522 } 2523 2524 public: 2525 CommandObjectTypeFilterAdd(CommandInterpreter &interpreter) 2526 : CommandObjectParsed(interpreter, "type filter add", 2527 "Add a new filter for a type.", nullptr) { 2528 CommandArgumentEntry type_arg; 2529 CommandArgumentData type_style_arg; 2530 2531 type_style_arg.arg_type = eArgTypeName; 2532 type_style_arg.arg_repetition = eArgRepeatPlus; 2533 2534 type_arg.push_back(type_style_arg); 2535 2536 m_arguments.push_back(type_arg); 2537 2538 SetHelpLong( 2539 R"( 2540 The following examples of 'type filter add' refer to this code snippet for context: 2541 2542 class Foo { 2543 int a; 2544 int b; 2545 int c; 2546 int d; 2547 int e; 2548 int f; 2549 int g; 2550 int h; 2551 int i; 2552 } 2553 Foo my_foo; 2554 2555 Adding a simple filter: 2556 2557 (lldb) type filter add --child a --child g Foo 2558 (lldb) frame variable my_foo 2559 2560 )" 2561 "Produces output where only a and g are displayed. Other children of my_foo \ 2562 (b, c, d, e, f, h and i) are available by asking for them explicitly:" 2563 R"( 2564 2565 (lldb) frame variable my_foo.b my_foo.c my_foo.i 2566 2567 )" 2568 "The formatting option --raw on frame variable bypasses the filter, showing \ 2569 all children of my_foo as if no filter was defined:" 2570 R"( 2571 2572 (lldb) frame variable my_foo --raw)"); 2573 } 2574 2575 ~CommandObjectTypeFilterAdd() override = default; 2576 2577 protected: 2578 bool DoExecute(Args &command, CommandReturnObject &result) override { 2579 const size_t argc = command.GetArgumentCount(); 2580 2581 if (argc < 1) { 2582 result.AppendErrorWithFormat("%s takes one or more args.\n", 2583 m_cmd_name.c_str()); 2584 return false; 2585 } 2586 2587 if (m_options.m_expr_paths.empty()) { 2588 result.AppendErrorWithFormat("%s needs one or more children.\n", 2589 m_cmd_name.c_str()); 2590 return false; 2591 } 2592 2593 TypeFilterImplSP entry(new TypeFilterImpl( 2594 SyntheticChildren::Flags() 2595 .SetCascades(m_options.m_cascade) 2596 .SetSkipPointers(m_options.m_skip_pointers) 2597 .SetSkipReferences(m_options.m_skip_references))); 2598 2599 // go through the expression paths 2600 CommandOptions::ExpressionPathsIterator begin, 2601 end = m_options.m_expr_paths.end(); 2602 2603 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++) 2604 entry->AddExpressionPath(*begin); 2605 2606 // now I have a valid provider, let's add it to every type 2607 2608 lldb::TypeCategoryImplSP category; 2609 DataVisualization::Categories::GetCategory( 2610 ConstString(m_options.m_category.c_str()), category); 2611 2612 Status error; 2613 2614 WarnOnPotentialUnquotedUnsignedType(command, result); 2615 2616 for (auto &arg_entry : command.entries()) { 2617 if (arg_entry.ref().empty()) { 2618 result.AppendError("empty typenames not allowed"); 2619 return false; 2620 } 2621 2622 ConstString typeCS(arg_entry.ref()); 2623 if (!AddFilter(typeCS, entry, 2624 m_options.m_regex ? eRegexFilter : eRegularFilter, 2625 m_options.m_category, &error)) { 2626 result.AppendError(error.AsCString()); 2627 return false; 2628 } 2629 } 2630 2631 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2632 return result.Succeeded(); 2633 } 2634 }; 2635 2636 // "type lookup" 2637 #define LLDB_OPTIONS_type_lookup 2638 #include "CommandOptions.inc" 2639 2640 class CommandObjectTypeLookup : public CommandObjectRaw { 2641 protected: 2642 // this function is allowed to do a more aggressive job at guessing languages 2643 // than the expression parser is comfortable with - so leave the original 2644 // call alone and add one that is specific to type lookup 2645 lldb::LanguageType GuessLanguage(StackFrame *frame) { 2646 lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown; 2647 2648 if (!frame) 2649 return lang_type; 2650 2651 lang_type = frame->GuessLanguage(); 2652 if (lang_type != lldb::eLanguageTypeUnknown) 2653 return lang_type; 2654 2655 Symbol *s = frame->GetSymbolContext(eSymbolContextSymbol).symbol; 2656 if (s) 2657 lang_type = s->GetMangled().GuessLanguage(); 2658 2659 return lang_type; 2660 } 2661 2662 class CommandOptions : public OptionGroup { 2663 public: 2664 CommandOptions() {} 2665 2666 ~CommandOptions() override = default; 2667 2668 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2669 return llvm::makeArrayRef(g_type_lookup_options); 2670 } 2671 2672 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 2673 ExecutionContext *execution_context) override { 2674 Status error; 2675 2676 const int short_option = g_type_lookup_options[option_idx].short_option; 2677 2678 switch (short_option) { 2679 case 'h': 2680 m_show_help = true; 2681 break; 2682 2683 case 'l': 2684 m_language = Language::GetLanguageTypeFromString(option_value); 2685 break; 2686 2687 default: 2688 llvm_unreachable("Unimplemented option"); 2689 } 2690 2691 return error; 2692 } 2693 2694 void OptionParsingStarting(ExecutionContext *execution_context) override { 2695 m_show_help = false; 2696 m_language = eLanguageTypeUnknown; 2697 } 2698 2699 // Options table: Required for subclasses of Options. 2700 2701 bool m_show_help = false; 2702 lldb::LanguageType m_language = eLanguageTypeUnknown; 2703 }; 2704 2705 OptionGroupOptions m_option_group; 2706 CommandOptions m_command_options; 2707 2708 public: 2709 CommandObjectTypeLookup(CommandInterpreter &interpreter) 2710 : CommandObjectRaw(interpreter, "type lookup", 2711 "Lookup types and declarations in the current target, " 2712 "following language-specific naming conventions.", 2713 "type lookup <type-specifier>", 2714 eCommandRequiresTarget) { 2715 m_option_group.Append(&m_command_options); 2716 m_option_group.Finalize(); 2717 } 2718 2719 ~CommandObjectTypeLookup() override = default; 2720 2721 Options *GetOptions() override { return &m_option_group; } 2722 2723 llvm::StringRef GetHelpLong() override { 2724 if (!m_cmd_help_long.empty()) 2725 return m_cmd_help_long; 2726 2727 StreamString stream; 2728 Language::ForEach([&](Language *lang) { 2729 if (const char *help = lang->GetLanguageSpecificTypeLookupHelp()) 2730 stream.Printf("%s\n", help); 2731 return true; 2732 }); 2733 2734 m_cmd_help_long = std::string(stream.GetString()); 2735 return m_cmd_help_long; 2736 } 2737 2738 bool DoExecute(llvm::StringRef raw_command_line, 2739 CommandReturnObject &result) override { 2740 if (raw_command_line.empty()) { 2741 result.AppendError( 2742 "type lookup cannot be invoked without a type name as argument"); 2743 return false; 2744 } 2745 2746 auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); 2747 m_option_group.NotifyOptionParsingStarting(&exe_ctx); 2748 2749 OptionsWithRaw args(raw_command_line); 2750 const char *name_of_type = args.GetRawPart().c_str(); 2751 2752 if (args.HasArgs()) 2753 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, 2754 exe_ctx)) 2755 return false; 2756 2757 ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope(); 2758 2759 bool any_found = false; 2760 2761 std::vector<Language *> languages; 2762 2763 bool is_global_search = false; 2764 LanguageType guessed_language = lldb::eLanguageTypeUnknown; 2765 2766 if ((is_global_search = 2767 (m_command_options.m_language == eLanguageTypeUnknown))) { 2768 Language::ForEach([&](Language *lang) { 2769 languages.push_back(lang); 2770 return true; 2771 }); 2772 } else { 2773 languages.push_back(Language::FindPlugin(m_command_options.m_language)); 2774 } 2775 2776 // This is not the most efficient way to do this, but we support very few 2777 // languages so the cost of the sort is going to be dwarfed by the actual 2778 // lookup anyway 2779 if (StackFrame *frame = m_exe_ctx.GetFramePtr()) { 2780 guessed_language = GuessLanguage(frame); 2781 if (guessed_language != eLanguageTypeUnknown) { 2782 llvm::sort( 2783 languages.begin(), languages.end(), 2784 [guessed_language](Language *lang1, Language *lang2) -> bool { 2785 if (!lang1 || !lang2) 2786 return false; 2787 LanguageType lt1 = lang1->GetLanguageType(); 2788 LanguageType lt2 = lang2->GetLanguageType(); 2789 if (lt1 == guessed_language) 2790 return true; // make the selected frame's language come first 2791 if (lt2 == guessed_language) 2792 return false; // make the selected frame's language come first 2793 return (lt1 < lt2); // normal comparison otherwise 2794 }); 2795 } 2796 } 2797 2798 bool is_first_language = true; 2799 2800 for (Language *language : languages) { 2801 if (!language) 2802 continue; 2803 2804 if (auto scavenger = language->GetTypeScavenger()) { 2805 Language::TypeScavenger::ResultSet search_results; 2806 if (scavenger->Find(best_scope, name_of_type, search_results) > 0) { 2807 for (const auto &search_result : search_results) { 2808 if (search_result && search_result->IsValid()) { 2809 any_found = true; 2810 search_result->DumpToStream(result.GetOutputStream(), 2811 this->m_command_options.m_show_help); 2812 } 2813 } 2814 } 2815 } 2816 // this is "type lookup SomeName" and we did find a match, so get out 2817 if (any_found && is_global_search) 2818 break; 2819 else if (is_first_language && is_global_search && 2820 guessed_language != lldb::eLanguageTypeUnknown) { 2821 is_first_language = false; 2822 result.GetOutputStream().Printf( 2823 "no type was found in the current language %s matching '%s'; " 2824 "performing a global search across all languages\n", 2825 Language::GetNameForLanguageType(guessed_language), name_of_type); 2826 } 2827 } 2828 2829 if (!any_found) 2830 result.AppendMessageWithFormat("no type was found matching '%s'\n", 2831 name_of_type); 2832 2833 result.SetStatus(any_found ? lldb::eReturnStatusSuccessFinishResult 2834 : lldb::eReturnStatusSuccessFinishNoResult); 2835 return true; 2836 } 2837 }; 2838 2839 template <typename FormatterType> 2840 class CommandObjectFormatterInfo : public CommandObjectRaw { 2841 public: 2842 typedef std::function<typename FormatterType::SharedPointer(ValueObject &)> 2843 DiscoveryFunction; 2844 CommandObjectFormatterInfo(CommandInterpreter &interpreter, 2845 const char *formatter_name, 2846 DiscoveryFunction discovery_func) 2847 : CommandObjectRaw(interpreter, "", "", "", eCommandRequiresFrame), 2848 m_formatter_name(formatter_name ? formatter_name : ""), 2849 m_discovery_function(discovery_func) { 2850 StreamString name; 2851 name.Printf("type %s info", formatter_name); 2852 SetCommandName(name.GetString()); 2853 StreamString help; 2854 help.Printf("This command evaluates the provided expression and shows " 2855 "which %s is applied to the resulting value (if any).", 2856 formatter_name); 2857 SetHelp(help.GetString()); 2858 StreamString syntax; 2859 syntax.Printf("type %s info <expr>", formatter_name); 2860 SetSyntax(syntax.GetString()); 2861 } 2862 2863 ~CommandObjectFormatterInfo() override = default; 2864 2865 protected: 2866 bool DoExecute(llvm::StringRef command, 2867 CommandReturnObject &result) override { 2868 TargetSP target_sp = GetDebugger().GetSelectedTarget(); 2869 Thread *thread = GetDefaultThread(); 2870 if (!thread) { 2871 result.AppendError("no default thread"); 2872 return false; 2873 } 2874 2875 StackFrameSP frame_sp = thread->GetSelectedFrame(); 2876 ValueObjectSP result_valobj_sp; 2877 EvaluateExpressionOptions options; 2878 lldb::ExpressionResults expr_result = target_sp->EvaluateExpression( 2879 command, frame_sp.get(), result_valobj_sp, options); 2880 if (expr_result == eExpressionCompleted && result_valobj_sp) { 2881 result_valobj_sp = 2882 result_valobj_sp->GetQualifiedRepresentationIfAvailable( 2883 target_sp->GetPreferDynamicValue(), 2884 target_sp->GetEnableSyntheticValue()); 2885 typename FormatterType::SharedPointer formatter_sp = 2886 m_discovery_function(*result_valobj_sp); 2887 if (formatter_sp) { 2888 std::string description(formatter_sp->GetDescription()); 2889 result.GetOutputStream() 2890 << m_formatter_name << " applied to (" 2891 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>") 2892 << ") " << command << " is: " << description << "\n"; 2893 result.SetStatus(lldb::eReturnStatusSuccessFinishResult); 2894 } else { 2895 result.GetOutputStream() 2896 << "no " << m_formatter_name << " applies to (" 2897 << result_valobj_sp->GetDisplayTypeName().AsCString("<unknown>") 2898 << ") " << command << "\n"; 2899 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 2900 } 2901 return true; 2902 } else { 2903 result.AppendError("failed to evaluate expression"); 2904 return false; 2905 } 2906 } 2907 2908 private: 2909 std::string m_formatter_name; 2910 DiscoveryFunction m_discovery_function; 2911 }; 2912 2913 class CommandObjectTypeFormat : public CommandObjectMultiword { 2914 public: 2915 CommandObjectTypeFormat(CommandInterpreter &interpreter) 2916 : CommandObjectMultiword( 2917 interpreter, "type format", 2918 "Commands for customizing value display formats.", 2919 "type format [<sub-command-options>] ") { 2920 LoadSubCommand( 2921 "add", CommandObjectSP(new CommandObjectTypeFormatAdd(interpreter))); 2922 LoadSubCommand("clear", CommandObjectSP( 2923 new CommandObjectTypeFormatClear(interpreter))); 2924 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFormatDelete( 2925 interpreter))); 2926 LoadSubCommand( 2927 "list", CommandObjectSP(new CommandObjectTypeFormatList(interpreter))); 2928 LoadSubCommand( 2929 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeFormatImpl>( 2930 interpreter, "format", 2931 [](ValueObject &valobj) -> TypeFormatImpl::SharedPointer { 2932 return valobj.GetValueFormat(); 2933 }))); 2934 } 2935 2936 ~CommandObjectTypeFormat() override = default; 2937 }; 2938 2939 #if LLDB_ENABLE_PYTHON 2940 2941 class CommandObjectTypeSynth : public CommandObjectMultiword { 2942 public: 2943 CommandObjectTypeSynth(CommandInterpreter &interpreter) 2944 : CommandObjectMultiword( 2945 interpreter, "type synthetic", 2946 "Commands for operating on synthetic type representations.", 2947 "type synthetic [<sub-command-options>] ") { 2948 LoadSubCommand("add", 2949 CommandObjectSP(new CommandObjectTypeSynthAdd(interpreter))); 2950 LoadSubCommand( 2951 "clear", CommandObjectSP(new CommandObjectTypeSynthClear(interpreter))); 2952 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSynthDelete( 2953 interpreter))); 2954 LoadSubCommand( 2955 "list", CommandObjectSP(new CommandObjectTypeSynthList(interpreter))); 2956 LoadSubCommand( 2957 "info", 2958 CommandObjectSP(new CommandObjectFormatterInfo<SyntheticChildren>( 2959 interpreter, "synthetic", 2960 [](ValueObject &valobj) -> SyntheticChildren::SharedPointer { 2961 return valobj.GetSyntheticChildren(); 2962 }))); 2963 } 2964 2965 ~CommandObjectTypeSynth() override = default; 2966 }; 2967 2968 #endif 2969 2970 class CommandObjectTypeFilter : public CommandObjectMultiword { 2971 public: 2972 CommandObjectTypeFilter(CommandInterpreter &interpreter) 2973 : CommandObjectMultiword(interpreter, "type filter", 2974 "Commands for operating on type filters.", 2975 "type filter [<sub-command-options>] ") { 2976 LoadSubCommand( 2977 "add", CommandObjectSP(new CommandObjectTypeFilterAdd(interpreter))); 2978 LoadSubCommand("clear", CommandObjectSP( 2979 new CommandObjectTypeFilterClear(interpreter))); 2980 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeFilterDelete( 2981 interpreter))); 2982 LoadSubCommand( 2983 "list", CommandObjectSP(new CommandObjectTypeFilterList(interpreter))); 2984 } 2985 2986 ~CommandObjectTypeFilter() override = default; 2987 }; 2988 2989 class CommandObjectTypeCategory : public CommandObjectMultiword { 2990 public: 2991 CommandObjectTypeCategory(CommandInterpreter &interpreter) 2992 : CommandObjectMultiword(interpreter, "type category", 2993 "Commands for operating on type categories.", 2994 "type category [<sub-command-options>] ") { 2995 LoadSubCommand( 2996 "define", 2997 CommandObjectSP(new CommandObjectTypeCategoryDefine(interpreter))); 2998 LoadSubCommand( 2999 "enable", 3000 CommandObjectSP(new CommandObjectTypeCategoryEnable(interpreter))); 3001 LoadSubCommand( 3002 "disable", 3003 CommandObjectSP(new CommandObjectTypeCategoryDisable(interpreter))); 3004 LoadSubCommand( 3005 "delete", 3006 CommandObjectSP(new CommandObjectTypeCategoryDelete(interpreter))); 3007 LoadSubCommand("list", CommandObjectSP( 3008 new CommandObjectTypeCategoryList(interpreter))); 3009 } 3010 3011 ~CommandObjectTypeCategory() override = default; 3012 }; 3013 3014 class CommandObjectTypeSummary : public CommandObjectMultiword { 3015 public: 3016 CommandObjectTypeSummary(CommandInterpreter &interpreter) 3017 : CommandObjectMultiword( 3018 interpreter, "type summary", 3019 "Commands for editing variable summary display options.", 3020 "type summary [<sub-command-options>] ") { 3021 LoadSubCommand( 3022 "add", CommandObjectSP(new CommandObjectTypeSummaryAdd(interpreter))); 3023 LoadSubCommand("clear", CommandObjectSP(new CommandObjectTypeSummaryClear( 3024 interpreter))); 3025 LoadSubCommand("delete", CommandObjectSP(new CommandObjectTypeSummaryDelete( 3026 interpreter))); 3027 LoadSubCommand( 3028 "list", CommandObjectSP(new CommandObjectTypeSummaryList(interpreter))); 3029 LoadSubCommand( 3030 "info", CommandObjectSP(new CommandObjectFormatterInfo<TypeSummaryImpl>( 3031 interpreter, "summary", 3032 [](ValueObject &valobj) -> TypeSummaryImpl::SharedPointer { 3033 return valobj.GetSummaryFormat(); 3034 }))); 3035 } 3036 3037 ~CommandObjectTypeSummary() override = default; 3038 }; 3039 3040 // CommandObjectType 3041 3042 CommandObjectType::CommandObjectType(CommandInterpreter &interpreter) 3043 : CommandObjectMultiword(interpreter, "type", 3044 "Commands for operating on the type system.", 3045 "type [<sub-command-options>]") { 3046 LoadSubCommand("category", 3047 CommandObjectSP(new CommandObjectTypeCategory(interpreter))); 3048 LoadSubCommand("filter", 3049 CommandObjectSP(new CommandObjectTypeFilter(interpreter))); 3050 LoadSubCommand("format", 3051 CommandObjectSP(new CommandObjectTypeFormat(interpreter))); 3052 LoadSubCommand("summary", 3053 CommandObjectSP(new CommandObjectTypeSummary(interpreter))); 3054 #if LLDB_ENABLE_PYTHON 3055 LoadSubCommand("synthetic", 3056 CommandObjectSP(new CommandObjectTypeSynth(interpreter))); 3057 #endif 3058 LoadSubCommand("lookup", 3059 CommandObjectSP(new CommandObjectTypeLookup(interpreter))); 3060 } 3061 3062 CommandObjectType::~CommandObjectType() = default; 3063