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