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