1 //===-- CommandObjectType.cpp ----------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "CommandObjectType.h" 11 12 // C Includes 13 14 #include <ctype.h> 15 16 // C++ Includes 17 18 #include "lldb/Core/DataVisualization.h" 19 #include "lldb/Core/ConstString.h" 20 #include "lldb/Core/Debugger.h" 21 #include "lldb/Core/InputReaderEZ.h" 22 #include "lldb/Core/RegularExpression.h" 23 #include "lldb/Core/State.h" 24 #include "lldb/Core/StringList.h" 25 #include "lldb/Interpreter/CommandInterpreter.h" 26 #include "lldb/Interpreter/CommandObject.h" 27 #include "lldb/Interpreter/CommandReturnObject.h" 28 #include "lldb/Interpreter/Options.h" 29 #include "lldb/Interpreter/OptionGroupFormat.h" 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 35 class ScriptAddOptions 36 { 37 38 public: 39 40 TypeSummaryImpl::Flags m_flags; 41 42 StringList m_target_types; 43 StringList m_user_source; 44 45 bool m_regex; 46 47 ConstString m_name; 48 49 std::string m_category; 50 51 ScriptAddOptions(const TypeSummaryImpl::Flags& flags, 52 bool regx, 53 const ConstString& name, 54 std::string catg) : 55 m_flags(flags), 56 m_regex(regx), 57 m_name(name), 58 m_category(catg) 59 { 60 } 61 62 typedef STD_SHARED_PTR(ScriptAddOptions) SharedPointer; 63 64 }; 65 66 class SynthAddOptions 67 { 68 69 public: 70 71 bool m_skip_pointers; 72 bool m_skip_references; 73 bool m_cascade; 74 bool m_regex; 75 StringList m_user_source; 76 StringList m_target_types; 77 78 std::string m_category; 79 80 SynthAddOptions(bool sptr, 81 bool sref, 82 bool casc, 83 bool regx, 84 std::string catg) : 85 m_skip_pointers(sptr), 86 m_skip_references(sref), 87 m_cascade(casc), 88 m_regex(regx), 89 m_user_source(), 90 m_target_types(), 91 m_category(catg) 92 { 93 } 94 95 typedef STD_SHARED_PTR(SynthAddOptions) SharedPointer; 96 97 }; 98 99 100 101 class CommandObjectTypeSummaryAdd : public CommandObject 102 { 103 104 private: 105 106 class CommandOptions : public Options 107 { 108 public: 109 110 CommandOptions (CommandInterpreter &interpreter) : 111 Options (interpreter) 112 { 113 } 114 115 virtual 116 ~CommandOptions (){} 117 118 virtual Error 119 SetOptionValue (uint32_t option_idx, const char *option_arg); 120 121 void 122 OptionParsingStarting (); 123 124 const OptionDefinition* 125 GetDefinitions () 126 { 127 return g_option_table; 128 } 129 130 // Options table: Required for subclasses of Options. 131 132 static OptionDefinition g_option_table[]; 133 134 // Instance variables to hold the values for command options. 135 136 TypeSummaryImpl::Flags m_flags; 137 bool m_regex; 138 std::string m_format_string; 139 ConstString m_name; 140 std::string m_python_script; 141 std::string m_python_function; 142 bool m_is_add_script; 143 std::string m_category; 144 }; 145 146 CommandOptions m_options; 147 148 virtual Options * 149 GetOptions () 150 { 151 return &m_options; 152 } 153 154 void 155 CollectPythonScript(ScriptAddOptions *options, 156 CommandReturnObject &result); 157 158 bool 159 Execute_ScriptSummary (Args& command, CommandReturnObject &result); 160 161 bool 162 Execute_StringSummary (Args& command, CommandReturnObject &result); 163 164 public: 165 166 enum SummaryFormatType 167 { 168 eRegularSummary, 169 eRegexSummary, 170 eNamedSummary 171 }; 172 173 CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter); 174 175 ~CommandObjectTypeSummaryAdd () 176 { 177 } 178 179 bool 180 Execute (Args& command, CommandReturnObject &result); 181 182 static bool 183 AddSummary(const ConstString& type_name, 184 lldb::TypeSummaryImplSP entry, 185 SummaryFormatType type, 186 std::string category, 187 Error* error = NULL); 188 }; 189 190 class CommandObjectTypeSynthAdd : public CommandObject 191 { 192 193 private: 194 195 class CommandOptions : public Options 196 { 197 public: 198 199 CommandOptions (CommandInterpreter &interpreter) : 200 Options (interpreter) 201 { 202 } 203 204 virtual 205 ~CommandOptions (){} 206 207 virtual Error 208 SetOptionValue (uint32_t option_idx, const char *option_arg) 209 { 210 Error error; 211 char short_option = (char) m_getopt_table[option_idx].val; 212 bool success; 213 214 switch (short_option) 215 { 216 case 'C': 217 m_cascade = Args::StringToBoolean(option_arg, true, &success); 218 if (!success) 219 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg); 220 break; 221 case 'P': 222 handwrite_python = true; 223 break; 224 case 'l': 225 m_class_name = std::string(option_arg); 226 is_class_based = true; 227 break; 228 case 'p': 229 m_skip_pointers = true; 230 break; 231 case 'r': 232 m_skip_references = true; 233 break; 234 case 'w': 235 m_category = std::string(option_arg); 236 break; 237 case 'x': 238 m_regex = true; 239 break; 240 default: 241 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 242 break; 243 } 244 245 return error; 246 } 247 248 void 249 OptionParsingStarting () 250 { 251 m_cascade = true; 252 m_class_name = ""; 253 m_skip_pointers = false; 254 m_skip_references = false; 255 m_category = "default"; 256 is_class_based = false; 257 handwrite_python = false; 258 m_regex = false; 259 } 260 261 const OptionDefinition* 262 GetDefinitions () 263 { 264 return g_option_table; 265 } 266 267 // Options table: Required for subclasses of Options. 268 269 static OptionDefinition g_option_table[]; 270 271 // Instance variables to hold the values for command options. 272 273 bool m_cascade; 274 bool m_skip_references; 275 bool m_skip_pointers; 276 std::string m_class_name; 277 bool m_input_python; 278 std::string m_category; 279 280 bool is_class_based; 281 282 bool handwrite_python; 283 284 bool m_regex; 285 286 }; 287 288 CommandOptions m_options; 289 290 virtual Options * 291 GetOptions () 292 { 293 return &m_options; 294 } 295 296 void 297 CollectPythonScript (SynthAddOptions *options, 298 CommandReturnObject &result); 299 bool 300 Execute_HandwritePython (Args& command, CommandReturnObject &result); 301 302 bool 303 Execute_PythonClass (Args& command, CommandReturnObject &result); 304 305 bool 306 Execute (Args& command, CommandReturnObject &result); 307 308 public: 309 310 enum SynthFormatType 311 { 312 eRegularSynth, 313 eRegexSynth 314 }; 315 316 CommandObjectTypeSynthAdd (CommandInterpreter &interpreter); 317 318 ~CommandObjectTypeSynthAdd () 319 { 320 } 321 322 static bool 323 AddSynth(const ConstString& type_name, 324 lldb::SyntheticChildrenSP entry, 325 SynthFormatType type, 326 std::string category_name, 327 Error* error); 328 }; 329 330 //------------------------------------------------------------------------- 331 // CommandObjectTypeFormatAdd 332 //------------------------------------------------------------------------- 333 334 class CommandObjectTypeFormatAdd : public CommandObject 335 { 336 337 private: 338 339 class CommandOptions : public OptionGroup 340 { 341 public: 342 343 CommandOptions () : 344 OptionGroup() 345 { 346 } 347 348 virtual 349 ~CommandOptions () 350 { 351 } 352 353 virtual uint32_t 354 GetNumDefinitions (); 355 356 virtual const OptionDefinition* 357 GetDefinitions () 358 { 359 return g_option_table; 360 } 361 362 virtual void 363 OptionParsingStarting (CommandInterpreter &interpreter) 364 { 365 m_cascade = true; 366 m_skip_pointers = false; 367 m_skip_references = false; 368 } 369 virtual Error 370 SetOptionValue (CommandInterpreter &interpreter, 371 uint32_t option_idx, 372 const char *option_value) 373 { 374 Error error; 375 const char short_option = (char) g_option_table[option_idx].short_option; 376 bool success; 377 378 switch (short_option) 379 { 380 case 'C': 381 m_cascade = Args::StringToBoolean(option_value, true, &success); 382 if (!success) 383 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_value); 384 break; 385 case 'p': 386 m_skip_pointers = true; 387 break; 388 case 'r': 389 m_skip_references = true; 390 break; 391 default: 392 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 393 break; 394 } 395 396 return error; 397 } 398 399 // Options table: Required for subclasses of Options. 400 401 static OptionDefinition g_option_table[]; 402 403 // Instance variables to hold the values for command options. 404 405 bool m_cascade; 406 bool m_skip_references; 407 bool m_skip_pointers; 408 }; 409 410 OptionGroupOptions m_option_group; 411 OptionGroupFormat m_format_options; 412 CommandOptions m_command_options; 413 414 virtual Options * 415 GetOptions () 416 { 417 return &m_option_group; 418 } 419 420 public: 421 CommandObjectTypeFormatAdd (CommandInterpreter &interpreter) : 422 CommandObject (interpreter, 423 "type format add", 424 "Add a new formatting style for a type.", 425 NULL), 426 m_option_group (interpreter), 427 m_format_options (eFormatInvalid), 428 m_command_options () 429 { 430 CommandArgumentEntry type_arg; 431 CommandArgumentData type_style_arg; 432 433 type_style_arg.arg_type = eArgTypeName; 434 type_style_arg.arg_repetition = eArgRepeatPlus; 435 436 type_arg.push_back (type_style_arg); 437 438 m_arguments.push_back (type_arg); 439 440 SetHelpLong( 441 "Some examples of using this command.\n" 442 "We use as reference the following snippet of code:\n" 443 "\n" 444 "typedef int Aint;\n" 445 "typedef float Afloat;\n" 446 "typedef Aint Bint;\n" 447 "typedef Afloat Bfloat;\n" 448 "\n" 449 "Aint ix = 5;\n" 450 "Bint iy = 5;\n" 451 "\n" 452 "Afloat fx = 3.14;\n" 453 "BFloat fy = 3.14;\n" 454 "\n" 455 "Typing:\n" 456 "type format add -f hex AInt\n" 457 "frame variable iy\n" 458 "will produce an hex display of iy, because no formatter is available for Bint and the one for Aint is used instead\n" 459 "To prevent this type\n" 460 "type format add -f hex -C no AInt\n" 461 "\n" 462 "A similar reasoning applies to\n" 463 "type format add -f hex -C no float -p\n" 464 "which now prints all floats and float&s as hexadecimal, but does not format float*s\n" 465 "and does not change the default display for Afloat and Bfloat objects.\n" 466 ); 467 468 // Add the "--format" to all options groups 469 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_ALL); 470 m_option_group.Append (&m_command_options); 471 m_option_group.Finalize(); 472 473 } 474 475 ~CommandObjectTypeFormatAdd () 476 { 477 } 478 479 bool 480 Execute (Args& command, CommandReturnObject &result) 481 { 482 const size_t argc = command.GetArgumentCount(); 483 484 if (argc < 1) 485 { 486 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 487 result.SetStatus(eReturnStatusFailed); 488 return false; 489 } 490 491 const Format format = m_format_options.GetFormat(); 492 if (format == eFormatInvalid) 493 { 494 result.AppendErrorWithFormat ("%s needs a valid format.\n", m_cmd_name.c_str()); 495 result.SetStatus(eReturnStatusFailed); 496 return false; 497 } 498 499 TypeFormatImplSP entry; 500 501 entry.reset(new TypeFormatImpl(format, 502 TypeFormatImpl::Flags().SetCascades(m_command_options.m_cascade). 503 SetSkipPointers(m_command_options.m_skip_pointers). 504 SetSkipReferences(m_command_options.m_skip_references))); 505 506 // now I have a valid format, let's add it to every type 507 508 for (size_t i = 0; i < argc; i++) 509 { 510 const char* typeA = command.GetArgumentAtIndex(i); 511 ConstString typeCS(typeA); 512 if (typeCS) 513 DataVisualization::ValueFormats::Add(typeCS, entry); 514 else 515 { 516 result.AppendError("empty typenames not allowed"); 517 result.SetStatus(eReturnStatusFailed); 518 return false; 519 } 520 } 521 522 result.SetStatus(eReturnStatusSuccessFinishNoResult); 523 return result.Succeeded(); 524 } 525 }; 526 527 OptionDefinition 528 CommandObjectTypeFormatAdd::CommandOptions::g_option_table[] = 529 { 530 { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, 531 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 532 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 533 }; 534 535 536 uint32_t 537 CommandObjectTypeFormatAdd::CommandOptions::GetNumDefinitions () 538 { 539 return sizeof(g_option_table) / sizeof (OptionDefinition); 540 } 541 542 543 //------------------------------------------------------------------------- 544 // CommandObjectTypeFormatDelete 545 //------------------------------------------------------------------------- 546 547 class CommandObjectTypeFormatDelete : public CommandObject 548 { 549 public: 550 CommandObjectTypeFormatDelete (CommandInterpreter &interpreter) : 551 CommandObject (interpreter, 552 "type format delete", 553 "Delete an existing formatting style for a type.", 554 NULL) 555 { 556 CommandArgumentEntry type_arg; 557 CommandArgumentData type_style_arg; 558 559 type_style_arg.arg_type = eArgTypeName; 560 type_style_arg.arg_repetition = eArgRepeatPlain; 561 562 type_arg.push_back (type_style_arg); 563 564 m_arguments.push_back (type_arg); 565 566 } 567 568 ~CommandObjectTypeFormatDelete () 569 { 570 } 571 572 bool 573 Execute (Args& command, CommandReturnObject &result) 574 { 575 const size_t argc = command.GetArgumentCount(); 576 577 if (argc != 1) 578 { 579 result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); 580 result.SetStatus(eReturnStatusFailed); 581 return false; 582 } 583 584 const char* typeA = command.GetArgumentAtIndex(0); 585 ConstString typeCS(typeA); 586 587 if (!typeCS) 588 { 589 result.AppendError("empty typenames not allowed"); 590 result.SetStatus(eReturnStatusFailed); 591 return false; 592 } 593 594 595 if (DataVisualization::ValueFormats::Delete(typeCS)) 596 { 597 result.SetStatus(eReturnStatusSuccessFinishNoResult); 598 return result.Succeeded(); 599 } 600 else 601 { 602 result.AppendErrorWithFormat ("no custom format for %s.\n", typeA); 603 result.SetStatus(eReturnStatusFailed); 604 return false; 605 } 606 607 } 608 609 }; 610 611 //------------------------------------------------------------------------- 612 // CommandObjectTypeFormatClear 613 //------------------------------------------------------------------------- 614 615 class CommandObjectTypeFormatClear : public CommandObject 616 { 617 public: 618 CommandObjectTypeFormatClear (CommandInterpreter &interpreter) : 619 CommandObject (interpreter, 620 "type format clear", 621 "Delete all existing format styles.", 622 NULL) 623 { 624 } 625 626 ~CommandObjectTypeFormatClear () 627 { 628 } 629 630 bool 631 Execute (Args& command, CommandReturnObject &result) 632 { 633 DataVisualization::ValueFormats::Clear(); 634 result.SetStatus(eReturnStatusSuccessFinishResult); 635 return result.Succeeded(); 636 } 637 638 }; 639 640 //------------------------------------------------------------------------- 641 // CommandObjectTypeFormatList 642 //------------------------------------------------------------------------- 643 644 bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeFormatImplSP& entry); 645 646 class CommandObjectTypeFormatList; 647 648 struct CommandObjectTypeFormatList_LoopCallbackParam { 649 CommandObjectTypeFormatList* self; 650 CommandReturnObject* result; 651 RegularExpression* regex; 652 CommandObjectTypeFormatList_LoopCallbackParam(CommandObjectTypeFormatList* S, CommandReturnObject* R, 653 RegularExpression* X = NULL) : self(S), result(R), regex(X) {} 654 }; 655 656 class CommandObjectTypeFormatList : public CommandObject 657 { 658 public: 659 CommandObjectTypeFormatList (CommandInterpreter &interpreter) : 660 CommandObject (interpreter, 661 "type format list", 662 "Show a list of current formatting styles.", 663 NULL) 664 { 665 CommandArgumentEntry type_arg; 666 CommandArgumentData type_style_arg; 667 668 type_style_arg.arg_type = eArgTypeName; 669 type_style_arg.arg_repetition = eArgRepeatOptional; 670 671 type_arg.push_back (type_style_arg); 672 673 m_arguments.push_back (type_arg); 674 } 675 676 ~CommandObjectTypeFormatList () 677 { 678 } 679 680 bool 681 Execute (Args& command, CommandReturnObject &result) 682 { 683 const size_t argc = command.GetArgumentCount(); 684 685 CommandObjectTypeFormatList_LoopCallbackParam *param; 686 687 if (argc == 1) 688 { 689 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 690 regex->Compile(command.GetArgumentAtIndex(0)); 691 param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result,regex); 692 } 693 else 694 param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result); 695 DataVisualization::ValueFormats::LoopThrough(CommandObjectTypeFormatList_LoopCallback, param); 696 delete param; 697 result.SetStatus(eReturnStatusSuccessFinishResult); 698 return result.Succeeded(); 699 } 700 701 private: 702 703 bool 704 LoopCallback (ConstString type, 705 const lldb::TypeFormatImplSP& entry, 706 RegularExpression* regex, 707 CommandReturnObject *result) 708 { 709 if (regex == NULL || regex->Execute(type.AsCString())) 710 { 711 result->GetOutputStream().Printf ("%s: %s\n", type.AsCString(), 712 entry->GetDescription().c_str()); 713 } 714 return true; 715 } 716 717 friend bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeFormatImplSP& entry); 718 719 }; 720 721 bool 722 CommandObjectTypeFormatList_LoopCallback ( 723 void* pt2self, 724 ConstString type, 725 const lldb::TypeFormatImplSP& entry) 726 { 727 CommandObjectTypeFormatList_LoopCallbackParam* param = (CommandObjectTypeFormatList_LoopCallbackParam*)pt2self; 728 return param->self->LoopCallback(type, entry, param->regex, param->result); 729 } 730 731 732 #ifndef LLDB_DISABLE_PYTHON 733 734 //------------------------------------------------------------------------- 735 // CommandObjectTypeSummaryAdd 736 //------------------------------------------------------------------------- 737 738 static const char *g_summary_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" 739 "def function (valobj,dict):"; 740 741 class TypeScriptAddInputReader : public InputReaderEZ 742 { 743 private: 744 DISALLOW_COPY_AND_ASSIGN (TypeScriptAddInputReader); 745 public: 746 TypeScriptAddInputReader(Debugger& debugger) : 747 InputReaderEZ(debugger) 748 {} 749 750 virtual 751 ~TypeScriptAddInputReader() 752 { 753 } 754 755 virtual void ActivateHandler(HandlerData& data) 756 { 757 StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); 758 bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); 759 if (!batch_mode) 760 { 761 out_stream->Printf ("%s\n", g_summary_addreader_instructions); 762 if (data.reader.GetPrompt()) 763 out_stream->Printf ("%s", data.reader.GetPrompt()); 764 out_stream->Flush(); 765 } 766 } 767 768 virtual void ReactivateHandler(HandlerData& data) 769 { 770 StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); 771 bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); 772 if (data.reader.GetPrompt() && !batch_mode) 773 { 774 out_stream->Printf ("%s", data.reader.GetPrompt()); 775 out_stream->Flush(); 776 } 777 } 778 virtual void GotTokenHandler(HandlerData& data) 779 { 780 StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); 781 bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); 782 if (data.bytes && data.bytes_len && data.baton) 783 { 784 ((ScriptAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len); 785 } 786 if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode) 787 { 788 out_stream->Printf ("%s", data.reader.GetPrompt()); 789 out_stream->Flush(); 790 } 791 } 792 virtual void InterruptHandler(HandlerData& data) 793 { 794 StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); 795 bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); 796 data.reader.SetIsDone (true); 797 if (!batch_mode) 798 { 799 out_stream->Printf ("Warning: No command attached to breakpoint.\n"); 800 out_stream->Flush(); 801 } 802 } 803 virtual void EOFHandler(HandlerData& data) 804 { 805 data.reader.SetIsDone (true); 806 } 807 virtual void DoneHandler(HandlerData& data) 808 { 809 StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); 810 ScriptAddOptions *options_ptr = ((ScriptAddOptions*)data.baton); 811 if (!options_ptr) 812 { 813 out_stream->Printf ("Internal error #1: no script attached.\n"); 814 out_stream->Flush(); 815 return; 816 } 817 818 ScriptAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope 819 820 ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 821 if (!interpreter) 822 { 823 out_stream->Printf ("Internal error #2: no script attached.\n"); 824 out_stream->Flush(); 825 return; 826 } 827 std::string funct_name_str; 828 if (!interpreter->GenerateTypeScriptFunction (options->m_user_source, 829 funct_name_str)) 830 { 831 out_stream->Printf ("Internal error #3: no script attached.\n"); 832 out_stream->Flush(); 833 return; 834 } 835 if (funct_name_str.empty()) 836 { 837 out_stream->Printf ("Internal error #4: no script attached.\n"); 838 out_stream->Flush(); 839 return; 840 } 841 // now I have a valid function name, let's add this as script for every type in the list 842 843 TypeSummaryImplSP script_format; 844 script_format.reset(new ScriptSummaryFormat(options->m_flags, 845 funct_name_str.c_str(), 846 options->m_user_source.CopyList(" ").c_str())); 847 848 Error error; 849 850 for (size_t i = 0; i < options->m_target_types.GetSize(); i++) 851 { 852 const char *type_name = options->m_target_types.GetStringAtIndex(i); 853 CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name), 854 script_format, 855 (options->m_regex ? CommandObjectTypeSummaryAdd::eRegexSummary : CommandObjectTypeSummaryAdd::eRegularSummary), 856 options->m_category, 857 &error); 858 if (error.Fail()) 859 { 860 out_stream->Printf ("%s", error.AsCString()); 861 out_stream->Flush(); 862 return; 863 } 864 } 865 866 if (options->m_name) 867 { 868 CommandObjectTypeSummaryAdd::AddSummary (options->m_name, 869 script_format, 870 CommandObjectTypeSummaryAdd::eNamedSummary, 871 options->m_category, 872 &error); 873 if (error.Fail()) 874 { 875 CommandObjectTypeSummaryAdd::AddSummary (options->m_name, 876 script_format, 877 CommandObjectTypeSummaryAdd::eNamedSummary, 878 options->m_category, 879 &error); 880 if (error.Fail()) 881 { 882 out_stream->Printf ("%s", error.AsCString()); 883 out_stream->Flush(); 884 return; 885 } 886 } 887 else 888 { 889 out_stream->Printf ("%s", error.AsCString()); 890 out_stream->Flush(); 891 return; 892 } 893 } 894 else 895 { 896 if (error.AsCString()) 897 { 898 out_stream->PutCString (error.AsCString()); 899 out_stream->Flush(); 900 } 901 return; 902 } 903 } 904 }; 905 906 #endif // #ifndef LLDB_DISABLE_PYTHON 907 908 Error 909 CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) 910 { 911 Error error; 912 char short_option = (char) m_getopt_table[option_idx].val; 913 bool success; 914 915 switch (short_option) 916 { 917 case 'C': 918 m_flags.SetCascades(Args::StringToBoolean(option_arg, true, &success)); 919 if (!success) 920 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg); 921 break; 922 case 'e': 923 m_flags.SetDontShowChildren(false); 924 break; 925 case 'v': 926 m_flags.SetDontShowValue(true); 927 break; 928 case 'c': 929 m_flags.SetShowMembersOneLiner(true); 930 break; 931 case 's': 932 m_format_string = std::string(option_arg); 933 break; 934 case 'p': 935 m_flags.SetSkipPointers(true); 936 break; 937 case 'r': 938 m_flags.SetSkipReferences(true); 939 break; 940 case 'x': 941 m_regex = true; 942 break; 943 case 'n': 944 m_name.SetCString(option_arg); 945 break; 946 case 'o': 947 m_python_script = std::string(option_arg); 948 m_is_add_script = true; 949 break; 950 case 'F': 951 m_python_function = std::string(option_arg); 952 m_is_add_script = true; 953 break; 954 case 'P': 955 m_is_add_script = true; 956 break; 957 case 'w': 958 m_category = std::string(option_arg); 959 break; 960 case 'O': 961 m_flags.SetHideItemNames(true); 962 break; 963 default: 964 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 965 break; 966 } 967 968 return error; 969 } 970 971 void 972 CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting () 973 { 974 m_flags.Clear().SetCascades().SetDontShowChildren().SetDontShowValue(false); 975 m_flags.SetShowMembersOneLiner(false).SetSkipPointers(false).SetSkipReferences(false).SetHideItemNames(false); 976 977 m_regex = false; 978 m_name.Clear(); 979 m_python_script = ""; 980 m_python_function = ""; 981 m_format_string = ""; 982 m_is_add_script = false; 983 m_category = "default"; 984 } 985 986 #ifndef LLDB_DISABLE_PYTHON 987 void 988 CommandObjectTypeSummaryAdd::CollectPythonScript (ScriptAddOptions *options, 989 CommandReturnObject &result) 990 { 991 InputReaderSP reader_sp (new TypeScriptAddInputReader(m_interpreter.GetDebugger())); 992 if (reader_sp && options) 993 { 994 995 InputReaderEZ::InitializationParameters ipr; 996 997 Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt(" "))); 998 if (err.Success()) 999 { 1000 m_interpreter.GetDebugger().PushInputReader (reader_sp); 1001 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1002 } 1003 else 1004 { 1005 result.AppendError (err.AsCString()); 1006 result.SetStatus (eReturnStatusFailed); 1007 } 1008 } 1009 else 1010 { 1011 result.AppendError("out of memory"); 1012 result.SetStatus (eReturnStatusFailed); 1013 } 1014 } 1015 1016 bool 1017 CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturnObject &result) 1018 { 1019 const size_t argc = command.GetArgumentCount(); 1020 1021 if (argc < 1 && !m_options.m_name) 1022 { 1023 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 1024 result.SetStatus(eReturnStatusFailed); 1025 return false; 1026 } 1027 1028 TypeSummaryImplSP script_format; 1029 1030 if (!m_options.m_python_function.empty()) // we have a Python function ready to use 1031 { 1032 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 1033 if (!interpreter) 1034 { 1035 result.AppendError ("Internal error #1N: no script attached.\n"); 1036 result.SetStatus (eReturnStatusFailed); 1037 return false; 1038 } 1039 const char *funct_name = m_options.m_python_function.c_str(); 1040 if (!funct_name || !funct_name[0]) 1041 { 1042 result.AppendError ("Internal error #2N: no script attached.\n"); 1043 result.SetStatus (eReturnStatusFailed); 1044 return false; 1045 } 1046 1047 std::string code = (" " + m_options.m_python_function + "(valobj,dict)"); 1048 1049 script_format.reset(new ScriptSummaryFormat(m_options.m_flags, 1050 funct_name, 1051 code.c_str())); 1052 } 1053 else if (!m_options.m_python_script.empty()) // we have a quick 1-line script, just use it 1054 { 1055 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 1056 if (!interpreter) 1057 { 1058 result.AppendError ("Internal error #1Q: no script attached.\n"); 1059 result.SetStatus (eReturnStatusFailed); 1060 return false; 1061 } 1062 StringList funct_sl; 1063 funct_sl << m_options.m_python_script.c_str(); 1064 std::string funct_name_str; 1065 if (!interpreter->GenerateTypeScriptFunction (funct_sl, 1066 funct_name_str)) 1067 { 1068 result.AppendError ("Internal error #2Q: no script attached.\n"); 1069 result.SetStatus (eReturnStatusFailed); 1070 return false; 1071 } 1072 if (funct_name_str.empty()) 1073 { 1074 result.AppendError ("Internal error #3Q: no script attached.\n"); 1075 result.SetStatus (eReturnStatusFailed); 1076 return false; 1077 } 1078 1079 std::string code = " " + m_options.m_python_script; 1080 1081 script_format.reset(new ScriptSummaryFormat(m_options.m_flags, 1082 funct_name_str.c_str(), 1083 code.c_str())); 1084 } 1085 else // use an InputReader to grab Python code from the user 1086 { 1087 ScriptAddOptions *options = new ScriptAddOptions(m_options.m_flags, 1088 m_options.m_regex, 1089 m_options.m_name, 1090 m_options.m_category); 1091 1092 for (size_t i = 0; i < argc; i++) 1093 { 1094 const char* typeA = command.GetArgumentAtIndex(i); 1095 if (typeA && *typeA) 1096 options->m_target_types << typeA; 1097 else 1098 { 1099 result.AppendError("empty typenames not allowed"); 1100 result.SetStatus(eReturnStatusFailed); 1101 return false; 1102 } 1103 } 1104 1105 CollectPythonScript(options,result); 1106 return result.Succeeded(); 1107 } 1108 1109 // if I am here, script_format must point to something good, so I can add that 1110 // as a script summary to all interested parties 1111 1112 Error error; 1113 1114 for (size_t i = 0; i < command.GetArgumentCount(); i++) 1115 { 1116 const char *type_name = command.GetArgumentAtIndex(i); 1117 CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name), 1118 script_format, 1119 (m_options.m_regex ? eRegexSummary : eRegularSummary), 1120 m_options.m_category, 1121 &error); 1122 if (error.Fail()) 1123 { 1124 result.AppendError(error.AsCString()); 1125 result.SetStatus(eReturnStatusFailed); 1126 return false; 1127 } 1128 } 1129 1130 if (m_options.m_name) 1131 { 1132 AddSummary(m_options.m_name, script_format, eNamedSummary, m_options.m_category, &error); 1133 if (error.Fail()) 1134 { 1135 result.AppendError(error.AsCString()); 1136 result.AppendError("added to types, but not given a name"); 1137 result.SetStatus(eReturnStatusFailed); 1138 return false; 1139 } 1140 } 1141 1142 return result.Succeeded(); 1143 } 1144 1145 #endif 1146 1147 1148 bool 1149 CommandObjectTypeSummaryAdd::Execute_StringSummary (Args& command, CommandReturnObject &result) 1150 { 1151 const size_t argc = command.GetArgumentCount(); 1152 1153 if (argc < 1 && !m_options.m_name) 1154 { 1155 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 1156 result.SetStatus(eReturnStatusFailed); 1157 return false; 1158 } 1159 1160 if (!m_options.m_flags.GetShowMembersOneLiner() && m_options.m_format_string.empty()) 1161 { 1162 result.AppendError("empty summary strings not allowed"); 1163 result.SetStatus(eReturnStatusFailed); 1164 return false; 1165 } 1166 1167 const char* format_cstr = (m_options.m_flags.GetShowMembersOneLiner() ? "" : m_options.m_format_string.c_str()); 1168 1169 // ${var%S} is an endless recursion, prevent it 1170 if (strcmp(format_cstr, "${var%S}") == 0) 1171 { 1172 result.AppendError("recursive summary not allowed"); 1173 result.SetStatus(eReturnStatusFailed); 1174 return false; 1175 } 1176 1177 Error error; 1178 1179 lldb::TypeSummaryImplSP entry(new StringSummaryFormat(m_options.m_flags, 1180 format_cstr)); 1181 1182 if (error.Fail()) 1183 { 1184 result.AppendError(error.AsCString()); 1185 result.SetStatus(eReturnStatusFailed); 1186 return false; 1187 } 1188 1189 // now I have a valid format, let's add it to every type 1190 1191 for (size_t i = 0; i < argc; i++) 1192 { 1193 const char* typeA = command.GetArgumentAtIndex(i); 1194 if (!typeA || typeA[0] == '\0') 1195 { 1196 result.AppendError("empty typenames not allowed"); 1197 result.SetStatus(eReturnStatusFailed); 1198 return false; 1199 } 1200 ConstString typeCS(typeA); 1201 1202 AddSummary(typeCS, 1203 entry, 1204 (m_options.m_regex ? eRegexSummary : eRegularSummary), 1205 m_options.m_category, 1206 &error); 1207 1208 if (error.Fail()) 1209 { 1210 result.AppendError(error.AsCString()); 1211 result.SetStatus(eReturnStatusFailed); 1212 return false; 1213 } 1214 } 1215 1216 if (m_options.m_name) 1217 { 1218 AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category, &error); 1219 if (error.Fail()) 1220 { 1221 result.AppendError(error.AsCString()); 1222 result.AppendError("added to types, but not given a name"); 1223 result.SetStatus(eReturnStatusFailed); 1224 return false; 1225 } 1226 } 1227 1228 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1229 return result.Succeeded(); 1230 } 1231 1232 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter) : 1233 CommandObject (interpreter, 1234 "type summary add", 1235 "Add a new summary style for a type.", 1236 NULL), m_options (interpreter) 1237 { 1238 CommandArgumentEntry type_arg; 1239 CommandArgumentData type_style_arg; 1240 1241 type_style_arg.arg_type = eArgTypeName; 1242 type_style_arg.arg_repetition = eArgRepeatPlus; 1243 1244 type_arg.push_back (type_style_arg); 1245 1246 m_arguments.push_back (type_arg); 1247 1248 SetHelpLong( 1249 "Some examples of using this command.\n" 1250 "We use as reference the following snippet of code:\n" 1251 "struct JustADemo\n" 1252 "{\n" 1253 "int* ptr;\n" 1254 "float value;\n" 1255 "JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}\n" 1256 "};\n" 1257 "JustADemo object(42,3.14);\n" 1258 "struct AnotherDemo : public JustADemo\n" 1259 "{\n" 1260 "uint8_t byte;\n" 1261 "AnotherDemo(uint8_t b = 'E', int p = 1, float v = 0.1) : JustADemo(p,v), byte(b) {}\n" 1262 "};\n" 1263 "AnotherDemo *another_object = new AnotherDemo('E',42,3.14);\n" 1264 "\n" 1265 "type summary add --summary-string \"the answer is ${*var.ptr}\" JustADemo\n" 1266 "when typing frame variable object you will get \"the answer is 42\"\n" 1267 "type summary add --summary-string \"the answer is ${*var.ptr}, and the question is ${var.value}\" JustADemo\n" 1268 "when typing frame variable object you will get \"the answer is 42 and the question is 3.14\"\n" 1269 "\n" 1270 "Alternatively, you could also say\n" 1271 "type summary add --summary-string \"${var%V} -> ${*var}\" \"int *\"\n" 1272 "and replace the above summary string with\n" 1273 "type summary add --summary-string \"the answer is ${var.ptr}, and the question is ${var.value}\" JustADemo\n" 1274 "to obtain a similar result\n" 1275 "\n" 1276 "To add a summary valid for both JustADemo and AnotherDemo you can use the scoping operator, as in:\n" 1277 "type summary add --summary-string \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes\n" 1278 "\n" 1279 "This will be used for both variables of type JustADemo and AnotherDemo. To prevent this, change the -C to read -C no\n" 1280 "If you do not want pointers to be shown using that summary, you can use the -p option, as in:\n" 1281 "type summary add --summary-string \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes -p\n" 1282 "A similar option -r exists for references.\n" 1283 "\n" 1284 "If you simply want a one-line summary of the content of your variable, without typing an explicit string to that effect\n" 1285 "you can use the -c option, without giving any summary string:\n" 1286 "type summary add -c JustADemo\n" 1287 "frame variable object\n" 1288 "the output being similar to (ptr=0xsomeaddress, value=3.14)\n" 1289 "\n" 1290 "If you want to display some summary text, but also expand the structure of your object, you can add the -e option, as in:\n" 1291 "type summary add -e --summary-string \"*ptr = ${*var.ptr}\" JustADemo\n" 1292 "Here the value of the int* is displayed, followed by the standard LLDB sequence of children objects, one per line.\n" 1293 "to get an output like:\n" 1294 "\n" 1295 "*ptr = 42 {\n" 1296 " ptr = 0xsomeaddress\n" 1297 " value = 3.14\n" 1298 "}\n" 1299 "\n" 1300 "You can also add Python summaries, in which case you will use lldb public API to gather information from your variables" 1301 "and elaborate them to a meaningful summary inside a script written in Python. The variable object will be passed to your" 1302 "script as an SBValue object. The following example might help you when starting to use the Python summaries feature:\n" 1303 "type summary add JustADemo -o \"value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();\"\n" 1304 "If you prefer to type your scripts on multiple lines, you will use the -P option and then type your script, ending it with " 1305 "the word DONE on a line by itself to mark you're finished editing your code:\n" 1306 "(lldb)type summary add JustADemo -P\n" 1307 " value = valobj.GetChildMemberWithName('value');\n" 1308 " return 'My value is ' + value.GetValue();\n" 1309 "DONE\n" 1310 "(lldb) <-- type further LLDB commands here\n" 1311 ); 1312 } 1313 1314 bool 1315 CommandObjectTypeSummaryAdd::Execute (Args& command, CommandReturnObject &result) 1316 { 1317 if (m_options.m_is_add_script) 1318 { 1319 #ifndef LLDB_DISABLE_PYTHON 1320 return Execute_ScriptSummary(command, result); 1321 #else 1322 result.AppendError ("python is disabled"); 1323 result.SetStatus(eReturnStatusFailed); 1324 return false; 1325 #endif 1326 } 1327 1328 return Execute_StringSummary(command, result); 1329 } 1330 1331 bool 1332 CommandObjectTypeSummaryAdd::AddSummary(const ConstString& type_name, 1333 TypeSummaryImplSP entry, 1334 SummaryFormatType type, 1335 std::string category_name, 1336 Error* error) 1337 { 1338 lldb::TypeCategoryImplSP category; 1339 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); 1340 1341 if (type == eRegexSummary) 1342 { 1343 RegularExpressionSP typeRX(new RegularExpression()); 1344 if (!typeRX->Compile(type_name.GetCString())) 1345 { 1346 if (error) 1347 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 1348 return false; 1349 } 1350 1351 category->GetRegexSummaryNavigator()->Delete(type_name); 1352 category->GetRegexSummaryNavigator()->Add(typeRX, entry); 1353 1354 return true; 1355 } 1356 else if (type == eNamedSummary) 1357 { 1358 // system named summaries do not exist (yet?) 1359 DataVisualization::NamedSummaryFormats::Add(type_name,entry); 1360 return true; 1361 } 1362 else 1363 { 1364 category->GetSummaryNavigator()->Add(type_name, entry); 1365 return true; 1366 } 1367 } 1368 1369 OptionDefinition 1370 CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = 1371 { 1372 { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 1373 { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, 1374 { LLDB_OPT_SET_ALL, false, "no-value", 'v', no_argument, NULL, 0, eArgTypeNone, "Don't show the value, just show the summary, for this type."}, 1375 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 1376 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 1377 { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, 1378 { LLDB_OPT_SET_1 , true, "inline-children", 'c', no_argument, NULL, 0, eArgTypeNone, "If true, inline all child values into summary string."}, 1379 { LLDB_OPT_SET_1 , false, "omit-names", 'O', no_argument, NULL, 0, eArgTypeNone, "If true, omit value names in the summary display."}, 1380 { LLDB_OPT_SET_2 , true, "summary-string", 's', required_argument, NULL, 0, eArgTypeSummaryString, "Summary string used to display text and object contents."}, 1381 { LLDB_OPT_SET_3, false, "python-script", 'o', required_argument, NULL, 0, eArgTypePythonScript, "Give a one-liner Python script as part of the command."}, 1382 { LLDB_OPT_SET_3, false, "python-function", 'F', required_argument, NULL, 0, eArgTypePythonFunction, "Give the name of a Python function to use for this type."}, 1383 { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone, "Input Python code to use for this type manually."}, 1384 { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', no_argument, NULL, 0, eArgTypeNone, "Expand aggregate data types to show children on separate lines."}, 1385 { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', required_argument, NULL, 0, eArgTypeName, "A name for this summary string."}, 1386 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1387 }; 1388 1389 1390 //------------------------------------------------------------------------- 1391 // CommandObjectTypeSummaryDelete 1392 //------------------------------------------------------------------------- 1393 1394 class CommandObjectTypeSummaryDelete : public CommandObject 1395 { 1396 private: 1397 class CommandOptions : public Options 1398 { 1399 public: 1400 1401 CommandOptions (CommandInterpreter &interpreter) : 1402 Options (interpreter) 1403 { 1404 } 1405 1406 virtual 1407 ~CommandOptions (){} 1408 1409 virtual Error 1410 SetOptionValue (uint32_t option_idx, const char *option_arg) 1411 { 1412 Error error; 1413 char short_option = (char) m_getopt_table[option_idx].val; 1414 1415 switch (short_option) 1416 { 1417 case 'a': 1418 m_delete_all = true; 1419 break; 1420 case 'w': 1421 m_category = std::string(option_arg); 1422 break; 1423 default: 1424 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1425 break; 1426 } 1427 1428 return error; 1429 } 1430 1431 void 1432 OptionParsingStarting () 1433 { 1434 m_delete_all = false; 1435 m_category = "default"; 1436 } 1437 1438 const OptionDefinition* 1439 GetDefinitions () 1440 { 1441 return g_option_table; 1442 } 1443 1444 // Options table: Required for subclasses of Options. 1445 1446 static OptionDefinition g_option_table[]; 1447 1448 // Instance variables to hold the values for command options. 1449 1450 bool m_delete_all; 1451 std::string m_category; 1452 1453 }; 1454 1455 CommandOptions m_options; 1456 1457 virtual Options * 1458 GetOptions () 1459 { 1460 return &m_options; 1461 } 1462 1463 static bool 1464 PerCategoryCallback(void* param, 1465 const lldb::TypeCategoryImplSP& category_sp) 1466 { 1467 ConstString *name = (ConstString*)param; 1468 category_sp->Delete(*name, eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary); 1469 return true; 1470 } 1471 1472 public: 1473 CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) : 1474 CommandObject (interpreter, 1475 "type summary delete", 1476 "Delete an existing summary style for a type.", 1477 NULL), m_options(interpreter) 1478 { 1479 CommandArgumentEntry type_arg; 1480 CommandArgumentData type_style_arg; 1481 1482 type_style_arg.arg_type = eArgTypeName; 1483 type_style_arg.arg_repetition = eArgRepeatPlain; 1484 1485 type_arg.push_back (type_style_arg); 1486 1487 m_arguments.push_back (type_arg); 1488 1489 } 1490 1491 ~CommandObjectTypeSummaryDelete () 1492 { 1493 } 1494 1495 bool 1496 Execute (Args& command, CommandReturnObject &result) 1497 { 1498 const size_t argc = command.GetArgumentCount(); 1499 1500 if (argc != 1) 1501 { 1502 result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); 1503 result.SetStatus(eReturnStatusFailed); 1504 return false; 1505 } 1506 1507 const char* typeA = command.GetArgumentAtIndex(0); 1508 ConstString typeCS(typeA); 1509 1510 if (!typeCS) 1511 { 1512 result.AppendError("empty typenames not allowed"); 1513 result.SetStatus(eReturnStatusFailed); 1514 return false; 1515 } 1516 1517 if (m_options.m_delete_all) 1518 { 1519 DataVisualization::Categories::LoopThrough(PerCategoryCallback, &typeCS); 1520 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1521 return result.Succeeded(); 1522 } 1523 1524 lldb::TypeCategoryImplSP category; 1525 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 1526 1527 bool delete_category = category->Delete(typeCS, 1528 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary); 1529 bool delete_named = DataVisualization::NamedSummaryFormats::Delete(typeCS); 1530 1531 if (delete_category || delete_named) 1532 { 1533 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1534 return result.Succeeded(); 1535 } 1536 else 1537 { 1538 result.AppendErrorWithFormat ("no custom summary for %s.\n", typeA); 1539 result.SetStatus(eReturnStatusFailed); 1540 return false; 1541 } 1542 1543 } 1544 }; 1545 1546 OptionDefinition 1547 CommandObjectTypeSummaryDelete::CommandOptions::g_option_table[] = 1548 { 1549 { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Delete from every category."}, 1550 { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Delete from given category."}, 1551 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1552 }; 1553 1554 class CommandObjectTypeSummaryClear : public CommandObject 1555 { 1556 private: 1557 1558 class CommandOptions : public Options 1559 { 1560 public: 1561 1562 CommandOptions (CommandInterpreter &interpreter) : 1563 Options (interpreter) 1564 { 1565 } 1566 1567 virtual 1568 ~CommandOptions (){} 1569 1570 virtual Error 1571 SetOptionValue (uint32_t option_idx, const char *option_arg) 1572 { 1573 Error error; 1574 char short_option = (char) m_getopt_table[option_idx].val; 1575 1576 switch (short_option) 1577 { 1578 case 'a': 1579 m_delete_all = true; 1580 break; 1581 default: 1582 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1583 break; 1584 } 1585 1586 return error; 1587 } 1588 1589 void 1590 OptionParsingStarting () 1591 { 1592 m_delete_all = false; 1593 } 1594 1595 const OptionDefinition* 1596 GetDefinitions () 1597 { 1598 return g_option_table; 1599 } 1600 1601 // Options table: Required for subclasses of Options. 1602 1603 static OptionDefinition g_option_table[]; 1604 1605 // Instance variables to hold the values for command options. 1606 1607 bool m_delete_all; 1608 bool m_delete_named; 1609 }; 1610 1611 CommandOptions m_options; 1612 1613 virtual Options * 1614 GetOptions () 1615 { 1616 return &m_options; 1617 } 1618 1619 static bool 1620 PerCategoryCallback(void* param, 1621 const lldb::TypeCategoryImplSP& cate) 1622 { 1623 cate->GetSummaryNavigator()->Clear(); 1624 cate->GetRegexSummaryNavigator()->Clear(); 1625 return true; 1626 1627 } 1628 1629 public: 1630 CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) : 1631 CommandObject (interpreter, 1632 "type summary clear", 1633 "Delete all existing summary styles.", 1634 NULL), m_options(interpreter) 1635 { 1636 } 1637 1638 ~CommandObjectTypeSummaryClear () 1639 { 1640 } 1641 1642 bool 1643 Execute (Args& command, CommandReturnObject &result) 1644 { 1645 1646 if (m_options.m_delete_all) 1647 DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL); 1648 1649 else 1650 { 1651 lldb::TypeCategoryImplSP category; 1652 if (command.GetArgumentCount() > 0) 1653 { 1654 const char* cat_name = command.GetArgumentAtIndex(0); 1655 ConstString cat_nameCS(cat_name); 1656 DataVisualization::Categories::GetCategory(cat_nameCS, category); 1657 } 1658 else 1659 DataVisualization::Categories::GetCategory(ConstString(NULL), category); 1660 category->Clear(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary); 1661 } 1662 1663 DataVisualization::NamedSummaryFormats::Clear(); 1664 1665 result.SetStatus(eReturnStatusSuccessFinishResult); 1666 return result.Succeeded(); 1667 } 1668 1669 }; 1670 1671 OptionDefinition 1672 CommandObjectTypeSummaryClear::CommandOptions::g_option_table[] = 1673 { 1674 { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Clear every category."}, 1675 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1676 }; 1677 1678 //------------------------------------------------------------------------- 1679 // CommandObjectTypeSummaryList 1680 //------------------------------------------------------------------------- 1681 1682 bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, ConstString type, const StringSummaryFormat::SharedPointer& entry); 1683 bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const StringSummaryFormat::SharedPointer& entry); 1684 1685 class CommandObjectTypeSummaryList; 1686 1687 struct CommandObjectTypeSummaryList_LoopCallbackParam { 1688 CommandObjectTypeSummaryList* self; 1689 CommandReturnObject* result; 1690 RegularExpression* regex; 1691 RegularExpression* cate_regex; 1692 CommandObjectTypeSummaryList_LoopCallbackParam(CommandObjectTypeSummaryList* S, CommandReturnObject* R, 1693 RegularExpression* X = NULL, 1694 RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {} 1695 }; 1696 1697 class CommandObjectTypeSummaryList : public CommandObject 1698 { 1699 1700 class CommandOptions : public Options 1701 { 1702 public: 1703 1704 CommandOptions (CommandInterpreter &interpreter) : 1705 Options (interpreter) 1706 { 1707 } 1708 1709 virtual 1710 ~CommandOptions (){} 1711 1712 virtual Error 1713 SetOptionValue (uint32_t option_idx, const char *option_arg) 1714 { 1715 Error error; 1716 char short_option = (char) m_getopt_table[option_idx].val; 1717 1718 switch (short_option) 1719 { 1720 case 'w': 1721 m_category_regex = std::string(option_arg); 1722 break; 1723 default: 1724 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1725 break; 1726 } 1727 1728 return error; 1729 } 1730 1731 void 1732 OptionParsingStarting () 1733 { 1734 m_category_regex = ""; 1735 } 1736 1737 const OptionDefinition* 1738 GetDefinitions () 1739 { 1740 return g_option_table; 1741 } 1742 1743 // Options table: Required for subclasses of Options. 1744 1745 static OptionDefinition g_option_table[]; 1746 1747 // Instance variables to hold the values for command options. 1748 1749 std::string m_category_regex; 1750 1751 }; 1752 1753 CommandOptions m_options; 1754 1755 virtual Options * 1756 GetOptions () 1757 { 1758 return &m_options; 1759 } 1760 1761 public: 1762 CommandObjectTypeSummaryList (CommandInterpreter &interpreter) : 1763 CommandObject (interpreter, 1764 "type summary list", 1765 "Show a list of current summary styles.", 1766 NULL), m_options(interpreter) 1767 { 1768 CommandArgumentEntry type_arg; 1769 CommandArgumentData type_style_arg; 1770 1771 type_style_arg.arg_type = eArgTypeName; 1772 type_style_arg.arg_repetition = eArgRepeatOptional; 1773 1774 type_arg.push_back (type_style_arg); 1775 1776 m_arguments.push_back (type_arg); 1777 } 1778 1779 ~CommandObjectTypeSummaryList () 1780 { 1781 } 1782 1783 bool 1784 Execute (Args& command, CommandReturnObject &result) 1785 { 1786 const size_t argc = command.GetArgumentCount(); 1787 1788 CommandObjectTypeSummaryList_LoopCallbackParam *param; 1789 RegularExpression* cate_regex = 1790 m_options.m_category_regex.empty() ? NULL : 1791 new RegularExpression(m_options.m_category_regex.c_str()); 1792 1793 if (argc == 1) 1794 { 1795 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 1796 regex->Compile(command.GetArgumentAtIndex(0)); 1797 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex,cate_regex); 1798 } 1799 else 1800 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,NULL,cate_regex); 1801 1802 DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); 1803 1804 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) 1805 { 1806 result.GetOutputStream().Printf("Named summaries:\n"); 1807 if (argc == 1) 1808 { 1809 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 1810 regex->Compile(command.GetArgumentAtIndex(0)); 1811 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex); 1812 } 1813 else 1814 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result); 1815 DataVisualization::NamedSummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param); 1816 delete param; 1817 } 1818 1819 if (cate_regex) 1820 delete cate_regex; 1821 1822 result.SetStatus(eReturnStatusSuccessFinishResult); 1823 return result.Succeeded(); 1824 } 1825 1826 private: 1827 1828 static bool 1829 PerCategoryCallback(void* param_vp, 1830 const lldb::TypeCategoryImplSP& cate) 1831 { 1832 1833 CommandObjectTypeSummaryList_LoopCallbackParam* param = 1834 (CommandObjectTypeSummaryList_LoopCallbackParam*)param_vp; 1835 CommandReturnObject* result = param->result; 1836 1837 const char* cate_name = cate->GetName(); 1838 1839 // if the category is disabled or empty and there is no regex, just skip it 1840 if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary) == 0) && param->cate_regex == NULL) 1841 return true; 1842 1843 // if we have a regex and this category does not match it, just skip it 1844 if(param->cate_regex != NULL && param->cate_regex->Execute(cate_name) == false) 1845 return true; 1846 1847 result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n", 1848 cate_name, 1849 (cate->IsEnabled() ? "enabled" : "disabled")); 1850 1851 cate->GetSummaryNavigator()->LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param_vp); 1852 1853 if (cate->GetRegexSummaryNavigator()->GetCount() > 0) 1854 { 1855 result->GetOutputStream().Printf("Regex-based summaries (slower):\n"); 1856 cate->GetRegexSummaryNavigator()->LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, param_vp); 1857 } 1858 return true; 1859 } 1860 1861 1862 bool 1863 LoopCallback (const char* type, 1864 const lldb::TypeSummaryImplSP& entry, 1865 RegularExpression* regex, 1866 CommandReturnObject *result) 1867 { 1868 if (regex == NULL || regex->Execute(type)) 1869 result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); 1870 return true; 1871 } 1872 1873 friend bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeSummaryImplSP& entry); 1874 friend bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const lldb::TypeSummaryImplSP& entry); 1875 }; 1876 1877 bool 1878 CommandObjectTypeSummaryList_LoopCallback ( 1879 void* pt2self, 1880 ConstString type, 1881 const lldb::TypeSummaryImplSP& entry) 1882 { 1883 CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self; 1884 return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result); 1885 } 1886 1887 bool 1888 CommandObjectTypeRXSummaryList_LoopCallback ( 1889 void* pt2self, 1890 lldb::RegularExpressionSP regex, 1891 const lldb::TypeSummaryImplSP& entry) 1892 { 1893 CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self; 1894 return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); 1895 } 1896 1897 OptionDefinition 1898 CommandObjectTypeSummaryList::CommandOptions::g_option_table[] = 1899 { 1900 { LLDB_OPT_SET_ALL, false, "category-regex", 'w', required_argument, NULL, 0, eArgTypeName, "Only show categories matching this filter."}, 1901 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1902 }; 1903 1904 //------------------------------------------------------------------------- 1905 // CommandObjectTypeCategoryEnable 1906 //------------------------------------------------------------------------- 1907 1908 class CommandObjectTypeCategoryEnable : public CommandObject 1909 { 1910 public: 1911 CommandObjectTypeCategoryEnable (CommandInterpreter &interpreter) : 1912 CommandObject (interpreter, 1913 "type category enable", 1914 "Enable a category as a source of formatters.", 1915 NULL) 1916 { 1917 CommandArgumentEntry type_arg; 1918 CommandArgumentData type_style_arg; 1919 1920 type_style_arg.arg_type = eArgTypeName; 1921 type_style_arg.arg_repetition = eArgRepeatPlus; 1922 1923 type_arg.push_back (type_style_arg); 1924 1925 m_arguments.push_back (type_arg); 1926 1927 } 1928 1929 ~CommandObjectTypeCategoryEnable () 1930 { 1931 } 1932 1933 bool 1934 Execute (Args& command, CommandReturnObject &result) 1935 { 1936 const size_t argc = command.GetArgumentCount(); 1937 1938 if (argc < 1) 1939 { 1940 result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str()); 1941 result.SetStatus(eReturnStatusFailed); 1942 return false; 1943 } 1944 1945 for (int i = argc - 1; i >= 0; i--) 1946 { 1947 const char* typeA = command.GetArgumentAtIndex(i); 1948 ConstString typeCS(typeA); 1949 1950 if (!typeCS) 1951 { 1952 result.AppendError("empty category name not allowed"); 1953 result.SetStatus(eReturnStatusFailed); 1954 return false; 1955 } 1956 DataVisualization::Categories::Enable(typeCS); 1957 lldb::TypeCategoryImplSP cate; 1958 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate.get()) 1959 { 1960 if (cate->GetCount() == 0) 1961 { 1962 result.AppendWarning("empty category enabled (typo?)"); 1963 } 1964 } 1965 } 1966 1967 result.SetStatus(eReturnStatusSuccessFinishResult); 1968 return result.Succeeded(); 1969 } 1970 1971 }; 1972 1973 //------------------------------------------------------------------------- 1974 // CommandObjectTypeCategoryDelete 1975 //------------------------------------------------------------------------- 1976 1977 class CommandObjectTypeCategoryDelete : public CommandObject 1978 { 1979 public: 1980 CommandObjectTypeCategoryDelete (CommandInterpreter &interpreter) : 1981 CommandObject (interpreter, 1982 "type category delete", 1983 "Delete a category and all associated formatters.", 1984 NULL) 1985 { 1986 CommandArgumentEntry type_arg; 1987 CommandArgumentData type_style_arg; 1988 1989 type_style_arg.arg_type = eArgTypeName; 1990 type_style_arg.arg_repetition = eArgRepeatPlus; 1991 1992 type_arg.push_back (type_style_arg); 1993 1994 m_arguments.push_back (type_arg); 1995 1996 } 1997 1998 ~CommandObjectTypeCategoryDelete () 1999 { 2000 } 2001 2002 bool 2003 Execute (Args& command, CommandReturnObject &result) 2004 { 2005 const size_t argc = command.GetArgumentCount(); 2006 2007 if (argc < 1) 2008 { 2009 result.AppendErrorWithFormat ("%s takes 1 or more arg.\n", m_cmd_name.c_str()); 2010 result.SetStatus(eReturnStatusFailed); 2011 return false; 2012 } 2013 2014 bool success = true; 2015 2016 // the order is not relevant here 2017 for (int i = argc - 1; i >= 0; i--) 2018 { 2019 const char* typeA = command.GetArgumentAtIndex(i); 2020 ConstString typeCS(typeA); 2021 2022 if (!typeCS) 2023 { 2024 result.AppendError("empty category name not allowed"); 2025 result.SetStatus(eReturnStatusFailed); 2026 return false; 2027 } 2028 if (!DataVisualization::Categories::Delete(typeCS)) 2029 success = false; // keep deleting even if we hit an error 2030 } 2031 if (success) 2032 { 2033 result.SetStatus(eReturnStatusSuccessFinishResult); 2034 return result.Succeeded(); 2035 } 2036 else 2037 { 2038 result.AppendError("cannot delete one or more categories\n"); 2039 result.SetStatus(eReturnStatusFailed); 2040 return false; 2041 } 2042 } 2043 }; 2044 2045 //------------------------------------------------------------------------- 2046 // CommandObjectTypeCategoryDisable 2047 //------------------------------------------------------------------------- 2048 2049 class CommandObjectTypeCategoryDisable : public CommandObject 2050 { 2051 public: 2052 CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) : 2053 CommandObject (interpreter, 2054 "type category disable", 2055 "Disable a category as a source of formatters.", 2056 NULL) 2057 { 2058 CommandArgumentEntry type_arg; 2059 CommandArgumentData type_style_arg; 2060 2061 type_style_arg.arg_type = eArgTypeName; 2062 type_style_arg.arg_repetition = eArgRepeatPlus; 2063 2064 type_arg.push_back (type_style_arg); 2065 2066 m_arguments.push_back (type_arg); 2067 2068 } 2069 2070 ~CommandObjectTypeCategoryDisable () 2071 { 2072 } 2073 2074 bool 2075 Execute (Args& command, CommandReturnObject &result) 2076 { 2077 const size_t argc = command.GetArgumentCount(); 2078 2079 if (argc < 1) 2080 { 2081 result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str()); 2082 result.SetStatus(eReturnStatusFailed); 2083 return false; 2084 } 2085 2086 if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0) 2087 { 2088 uint32_t num_categories = DataVisualization::Categories::GetCount(); 2089 for (uint32_t i = 0; i < num_categories; i++) 2090 { 2091 lldb::TypeCategoryImplSP category_sp = DataVisualization::Categories::GetCategoryAtIndex(i); 2092 // no need to check if the category is enabled - disabling a disabled category has no effect 2093 if (category_sp) 2094 DataVisualization::Categories::Disable(category_sp); 2095 } 2096 } 2097 else 2098 { 2099 // the order is not relevant here 2100 for (int i = argc - 1; i >= 0; i--) 2101 { 2102 const char* typeA = command.GetArgumentAtIndex(i); 2103 ConstString typeCS(typeA); 2104 2105 if (!typeCS) 2106 { 2107 result.AppendError("empty category name not allowed"); 2108 result.SetStatus(eReturnStatusFailed); 2109 return false; 2110 } 2111 DataVisualization::Categories::Disable(typeCS); 2112 } 2113 } 2114 2115 result.SetStatus(eReturnStatusSuccessFinishResult); 2116 return result.Succeeded(); 2117 } 2118 2119 }; 2120 2121 //------------------------------------------------------------------------- 2122 // CommandObjectTypeCategoryList 2123 //------------------------------------------------------------------------- 2124 2125 class CommandObjectTypeCategoryList : public CommandObject 2126 { 2127 private: 2128 2129 struct CommandObjectTypeCategoryList_CallbackParam 2130 { 2131 CommandReturnObject* result; 2132 RegularExpression* regex; 2133 2134 CommandObjectTypeCategoryList_CallbackParam(CommandReturnObject* res, 2135 RegularExpression* rex = NULL) : 2136 result(res), 2137 regex(rex) 2138 { 2139 } 2140 2141 }; 2142 2143 static bool 2144 PerCategoryCallback(void* param_vp, 2145 const lldb::TypeCategoryImplSP& cate) 2146 { 2147 CommandObjectTypeCategoryList_CallbackParam* param = 2148 (CommandObjectTypeCategoryList_CallbackParam*)param_vp; 2149 CommandReturnObject* result = param->result; 2150 RegularExpression* regex = param->regex; 2151 2152 const char* cate_name = cate->GetName(); 2153 2154 if (regex == NULL || regex->Execute(cate_name)) 2155 result->GetOutputStream().Printf("Category %s is%s enabled\n", 2156 cate_name, 2157 (cate->IsEnabled() ? "" : " not")); 2158 return true; 2159 } 2160 public: 2161 CommandObjectTypeCategoryList (CommandInterpreter &interpreter) : 2162 CommandObject (interpreter, 2163 "type category list", 2164 "Provide a list of all existing categories.", 2165 NULL) 2166 { 2167 CommandArgumentEntry type_arg; 2168 CommandArgumentData type_style_arg; 2169 2170 type_style_arg.arg_type = eArgTypeName; 2171 type_style_arg.arg_repetition = eArgRepeatOptional; 2172 2173 type_arg.push_back (type_style_arg); 2174 2175 m_arguments.push_back (type_arg); 2176 } 2177 2178 ~CommandObjectTypeCategoryList () 2179 { 2180 } 2181 2182 bool 2183 Execute (Args& command, CommandReturnObject &result) 2184 { 2185 const size_t argc = command.GetArgumentCount(); 2186 RegularExpression* regex = NULL; 2187 2188 if (argc == 0) 2189 ; 2190 else if (argc == 1) 2191 regex = new RegularExpression(command.GetArgumentAtIndex(0)); 2192 else 2193 { 2194 result.AppendErrorWithFormat ("%s takes 0 or one arg.\n", m_cmd_name.c_str()); 2195 result.SetStatus(eReturnStatusFailed); 2196 return false; 2197 } 2198 2199 CommandObjectTypeCategoryList_CallbackParam param(&result, 2200 regex); 2201 2202 DataVisualization::Categories::LoopThrough(PerCategoryCallback, ¶m); 2203 2204 if (regex) 2205 delete regex; 2206 2207 result.SetStatus(eReturnStatusSuccessFinishResult); 2208 return result.Succeeded(); 2209 } 2210 2211 }; 2212 2213 //------------------------------------------------------------------------- 2214 // CommandObjectTypeFilterList 2215 //------------------------------------------------------------------------- 2216 2217 bool CommandObjectTypeFilterList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry); 2218 bool CommandObjectTypeFilterRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry); 2219 2220 class CommandObjectTypeFilterList; 2221 2222 struct CommandObjectTypeFilterList_LoopCallbackParam { 2223 CommandObjectTypeFilterList* self; 2224 CommandReturnObject* result; 2225 RegularExpression* regex; 2226 RegularExpression* cate_regex; 2227 CommandObjectTypeFilterList_LoopCallbackParam(CommandObjectTypeFilterList* S, CommandReturnObject* R, 2228 RegularExpression* X = NULL, 2229 RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {} 2230 }; 2231 2232 class CommandObjectTypeFilterList : public CommandObject 2233 { 2234 2235 class CommandOptions : public Options 2236 { 2237 public: 2238 2239 CommandOptions (CommandInterpreter &interpreter) : 2240 Options (interpreter) 2241 { 2242 } 2243 2244 virtual 2245 ~CommandOptions (){} 2246 2247 virtual Error 2248 SetOptionValue (uint32_t option_idx, const char *option_arg) 2249 { 2250 Error error; 2251 char short_option = (char) m_getopt_table[option_idx].val; 2252 2253 switch (short_option) 2254 { 2255 case 'w': 2256 m_category_regex = std::string(option_arg); 2257 break; 2258 default: 2259 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2260 break; 2261 } 2262 2263 return error; 2264 } 2265 2266 void 2267 OptionParsingStarting () 2268 { 2269 m_category_regex = ""; 2270 } 2271 2272 const OptionDefinition* 2273 GetDefinitions () 2274 { 2275 return g_option_table; 2276 } 2277 2278 // Options table: Required for subclasses of Options. 2279 2280 static OptionDefinition g_option_table[]; 2281 2282 // Instance variables to hold the values for command options. 2283 2284 std::string m_category_regex; 2285 2286 }; 2287 2288 CommandOptions m_options; 2289 2290 virtual Options * 2291 GetOptions () 2292 { 2293 return &m_options; 2294 } 2295 2296 public: 2297 CommandObjectTypeFilterList (CommandInterpreter &interpreter) : 2298 CommandObject (interpreter, 2299 "type filter list", 2300 "Show a list of current filters.", 2301 NULL), m_options(interpreter) 2302 { 2303 CommandArgumentEntry type_arg; 2304 CommandArgumentData type_style_arg; 2305 2306 type_style_arg.arg_type = eArgTypeName; 2307 type_style_arg.arg_repetition = eArgRepeatOptional; 2308 2309 type_arg.push_back (type_style_arg); 2310 2311 m_arguments.push_back (type_arg); 2312 } 2313 2314 ~CommandObjectTypeFilterList () 2315 { 2316 } 2317 2318 bool 2319 Execute (Args& command, CommandReturnObject &result) 2320 { 2321 const size_t argc = command.GetArgumentCount(); 2322 2323 CommandObjectTypeFilterList_LoopCallbackParam *param; 2324 RegularExpression* cate_regex = 2325 m_options.m_category_regex.empty() ? NULL : 2326 new RegularExpression(m_options.m_category_regex.c_str()); 2327 2328 if (argc == 1) 2329 { 2330 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 2331 regex->Compile(command.GetArgumentAtIndex(0)); 2332 param = new CommandObjectTypeFilterList_LoopCallbackParam(this,&result,regex,cate_regex); 2333 } 2334 else 2335 param = new CommandObjectTypeFilterList_LoopCallbackParam(this,&result,NULL,cate_regex); 2336 2337 DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); 2338 2339 if (cate_regex) 2340 delete cate_regex; 2341 2342 result.SetStatus(eReturnStatusSuccessFinishResult); 2343 return result.Succeeded(); 2344 } 2345 2346 private: 2347 2348 static bool 2349 PerCategoryCallback(void* param_vp, 2350 const lldb::TypeCategoryImplSP& cate) 2351 { 2352 2353 const char* cate_name = cate->GetName(); 2354 2355 CommandObjectTypeFilterList_LoopCallbackParam* param = 2356 (CommandObjectTypeFilterList_LoopCallbackParam*)param_vp; 2357 CommandReturnObject* result = param->result; 2358 2359 // if the category is disabled or empty and there is no regex, just skip it 2360 if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter) == 0) && param->cate_regex == NULL) 2361 return true; 2362 2363 // if we have a regex and this category does not match it, just skip it 2364 if(param->cate_regex != NULL && param->cate_regex->Execute(cate_name) == false) 2365 return true; 2366 2367 result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n", 2368 cate_name, 2369 (cate->IsEnabled() ? "enabled" : "disabled")); 2370 2371 cate->GetFilterNavigator()->LoopThrough(CommandObjectTypeFilterList_LoopCallback, param_vp); 2372 2373 if (cate->GetRegexFilterNavigator()->GetCount() > 0) 2374 { 2375 result->GetOutputStream().Printf("Regex-based filters (slower):\n"); 2376 cate->GetRegexFilterNavigator()->LoopThrough(CommandObjectTypeFilterRXList_LoopCallback, param_vp); 2377 } 2378 2379 return true; 2380 } 2381 2382 bool 2383 LoopCallback (const char* type, 2384 const SyntheticChildren::SharedPointer& entry, 2385 RegularExpression* regex, 2386 CommandReturnObject *result) 2387 { 2388 if (regex == NULL || regex->Execute(type)) 2389 result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); 2390 return true; 2391 } 2392 2393 friend bool CommandObjectTypeFilterList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry); 2394 friend bool CommandObjectTypeFilterRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry); 2395 }; 2396 2397 bool 2398 CommandObjectTypeFilterList_LoopCallback (void* pt2self, 2399 ConstString type, 2400 const SyntheticChildren::SharedPointer& entry) 2401 { 2402 CommandObjectTypeFilterList_LoopCallbackParam* param = (CommandObjectTypeFilterList_LoopCallbackParam*)pt2self; 2403 return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result); 2404 } 2405 2406 bool 2407 CommandObjectTypeFilterRXList_LoopCallback (void* pt2self, 2408 lldb::RegularExpressionSP regex, 2409 const SyntheticChildren::SharedPointer& entry) 2410 { 2411 CommandObjectTypeFilterList_LoopCallbackParam* param = (CommandObjectTypeFilterList_LoopCallbackParam*)pt2self; 2412 return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); 2413 } 2414 2415 2416 OptionDefinition 2417 CommandObjectTypeFilterList::CommandOptions::g_option_table[] = 2418 { 2419 { LLDB_OPT_SET_ALL, false, "category-regex", 'w', required_argument, NULL, 0, eArgTypeName, "Only show categories matching this filter."}, 2420 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 2421 }; 2422 2423 #ifndef LLDB_DISABLE_PYTHON 2424 2425 //------------------------------------------------------------------------- 2426 // CommandObjectTypeSynthList 2427 //------------------------------------------------------------------------- 2428 2429 bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry); 2430 bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry); 2431 2432 class CommandObjectTypeSynthList; 2433 2434 struct CommandObjectTypeSynthList_LoopCallbackParam { 2435 CommandObjectTypeSynthList* self; 2436 CommandReturnObject* result; 2437 RegularExpression* regex; 2438 RegularExpression* cate_regex; 2439 CommandObjectTypeSynthList_LoopCallbackParam(CommandObjectTypeSynthList* S, CommandReturnObject* R, 2440 RegularExpression* X = NULL, 2441 RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {} 2442 }; 2443 2444 class CommandObjectTypeSynthList : public CommandObject 2445 { 2446 2447 class CommandOptions : public Options 2448 { 2449 public: 2450 2451 CommandOptions (CommandInterpreter &interpreter) : 2452 Options (interpreter) 2453 { 2454 } 2455 2456 virtual 2457 ~CommandOptions (){} 2458 2459 virtual Error 2460 SetOptionValue (uint32_t option_idx, const char *option_arg) 2461 { 2462 Error error; 2463 char short_option = (char) m_getopt_table[option_idx].val; 2464 2465 switch (short_option) 2466 { 2467 case 'w': 2468 m_category_regex = std::string(option_arg); 2469 break; 2470 default: 2471 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2472 break; 2473 } 2474 2475 return error; 2476 } 2477 2478 void 2479 OptionParsingStarting () 2480 { 2481 m_category_regex = ""; 2482 } 2483 2484 const OptionDefinition* 2485 GetDefinitions () 2486 { 2487 return g_option_table; 2488 } 2489 2490 // Options table: Required for subclasses of Options. 2491 2492 static OptionDefinition g_option_table[]; 2493 2494 // Instance variables to hold the values for command options. 2495 2496 std::string m_category_regex; 2497 2498 }; 2499 2500 CommandOptions m_options; 2501 2502 virtual Options * 2503 GetOptions () 2504 { 2505 return &m_options; 2506 } 2507 2508 public: 2509 CommandObjectTypeSynthList (CommandInterpreter &interpreter) : 2510 CommandObject (interpreter, 2511 "type synthetic list", 2512 "Show a list of current synthetic providers.", 2513 NULL), m_options(interpreter) 2514 { 2515 CommandArgumentEntry type_arg; 2516 CommandArgumentData type_style_arg; 2517 2518 type_style_arg.arg_type = eArgTypeName; 2519 type_style_arg.arg_repetition = eArgRepeatOptional; 2520 2521 type_arg.push_back (type_style_arg); 2522 2523 m_arguments.push_back (type_arg); 2524 } 2525 2526 ~CommandObjectTypeSynthList () 2527 { 2528 } 2529 2530 bool 2531 Execute (Args& command, CommandReturnObject &result) 2532 { 2533 const size_t argc = command.GetArgumentCount(); 2534 2535 CommandObjectTypeSynthList_LoopCallbackParam *param; 2536 RegularExpression* cate_regex = 2537 m_options.m_category_regex.empty() ? NULL : 2538 new RegularExpression(m_options.m_category_regex.c_str()); 2539 2540 if (argc == 1) 2541 { 2542 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 2543 regex->Compile(command.GetArgumentAtIndex(0)); 2544 param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,regex,cate_regex); 2545 } 2546 else 2547 param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,NULL,cate_regex); 2548 2549 DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); 2550 2551 if (cate_regex) 2552 delete cate_regex; 2553 2554 result.SetStatus(eReturnStatusSuccessFinishResult); 2555 return result.Succeeded(); 2556 } 2557 2558 private: 2559 2560 static bool 2561 PerCategoryCallback(void* param_vp, 2562 const lldb::TypeCategoryImplSP& cate) 2563 { 2564 2565 CommandObjectTypeSynthList_LoopCallbackParam* param = 2566 (CommandObjectTypeSynthList_LoopCallbackParam*)param_vp; 2567 CommandReturnObject* result = param->result; 2568 2569 const char* cate_name = cate->GetName(); 2570 2571 // if the category is disabled or empty and there is no regex, just skip it 2572 if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth) == 0) && param->cate_regex == NULL) 2573 return true; 2574 2575 // if we have a regex and this category does not match it, just skip it 2576 if(param->cate_regex != NULL && param->cate_regex->Execute(cate_name) == false) 2577 return true; 2578 2579 result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n", 2580 cate_name, 2581 (cate->IsEnabled() ? "enabled" : "disabled")); 2582 2583 cate->GetSyntheticNavigator()->LoopThrough(CommandObjectTypeSynthList_LoopCallback, param_vp); 2584 2585 if (cate->GetRegexSyntheticNavigator()->GetCount() > 0) 2586 { 2587 result->GetOutputStream().Printf("Regex-based synthetic providers (slower):\n"); 2588 cate->GetRegexSyntheticNavigator()->LoopThrough(CommandObjectTypeSynthRXList_LoopCallback, param_vp); 2589 } 2590 2591 return true; 2592 } 2593 2594 bool 2595 LoopCallback (const char* type, 2596 const SyntheticChildren::SharedPointer& entry, 2597 RegularExpression* regex, 2598 CommandReturnObject *result) 2599 { 2600 if (regex == NULL || regex->Execute(type)) 2601 result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); 2602 return true; 2603 } 2604 2605 friend bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry); 2606 friend bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry); 2607 }; 2608 2609 bool 2610 CommandObjectTypeSynthList_LoopCallback (void* pt2self, 2611 ConstString type, 2612 const SyntheticChildren::SharedPointer& entry) 2613 { 2614 CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self; 2615 return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result); 2616 } 2617 2618 bool 2619 CommandObjectTypeSynthRXList_LoopCallback (void* pt2self, 2620 lldb::RegularExpressionSP regex, 2621 const SyntheticChildren::SharedPointer& entry) 2622 { 2623 CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self; 2624 return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); 2625 } 2626 2627 2628 OptionDefinition 2629 CommandObjectTypeSynthList::CommandOptions::g_option_table[] = 2630 { 2631 { LLDB_OPT_SET_ALL, false, "category-regex", 'w', required_argument, NULL, 0, eArgTypeName, "Only show categories matching this filter."}, 2632 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 2633 }; 2634 2635 #endif // #ifndef LLDB_DISABLE_PYTHON 2636 //------------------------------------------------------------------------- 2637 // CommandObjectTypeFilterDelete 2638 //------------------------------------------------------------------------- 2639 2640 class CommandObjectTypeFilterDelete : public CommandObject 2641 { 2642 private: 2643 class CommandOptions : public Options 2644 { 2645 public: 2646 2647 CommandOptions (CommandInterpreter &interpreter) : 2648 Options (interpreter) 2649 { 2650 } 2651 2652 virtual 2653 ~CommandOptions (){} 2654 2655 virtual Error 2656 SetOptionValue (uint32_t option_idx, const char *option_arg) 2657 { 2658 Error error; 2659 char short_option = (char) m_getopt_table[option_idx].val; 2660 2661 switch (short_option) 2662 { 2663 case 'a': 2664 m_delete_all = true; 2665 break; 2666 case 'w': 2667 m_category = std::string(option_arg); 2668 break; 2669 default: 2670 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2671 break; 2672 } 2673 2674 return error; 2675 } 2676 2677 void 2678 OptionParsingStarting () 2679 { 2680 m_delete_all = false; 2681 m_category = "default"; 2682 } 2683 2684 const OptionDefinition* 2685 GetDefinitions () 2686 { 2687 return g_option_table; 2688 } 2689 2690 // Options table: Required for subclasses of Options. 2691 2692 static OptionDefinition g_option_table[]; 2693 2694 // Instance variables to hold the values for command options. 2695 2696 bool m_delete_all; 2697 std::string m_category; 2698 2699 }; 2700 2701 CommandOptions m_options; 2702 2703 virtual Options * 2704 GetOptions () 2705 { 2706 return &m_options; 2707 } 2708 2709 static bool 2710 PerCategoryCallback(void* param, 2711 const lldb::TypeCategoryImplSP& cate) 2712 { 2713 ConstString *name = (ConstString*)param; 2714 return cate->Delete(*name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter); 2715 } 2716 2717 public: 2718 CommandObjectTypeFilterDelete (CommandInterpreter &interpreter) : 2719 CommandObject (interpreter, 2720 "type filter delete", 2721 "Delete an existing filter for a type.", 2722 NULL), m_options(interpreter) 2723 { 2724 CommandArgumentEntry type_arg; 2725 CommandArgumentData type_style_arg; 2726 2727 type_style_arg.arg_type = eArgTypeName; 2728 type_style_arg.arg_repetition = eArgRepeatPlain; 2729 2730 type_arg.push_back (type_style_arg); 2731 2732 m_arguments.push_back (type_arg); 2733 2734 } 2735 2736 ~CommandObjectTypeFilterDelete () 2737 { 2738 } 2739 2740 bool 2741 Execute (Args& command, CommandReturnObject &result) 2742 { 2743 const size_t argc = command.GetArgumentCount(); 2744 2745 if (argc != 1) 2746 { 2747 result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); 2748 result.SetStatus(eReturnStatusFailed); 2749 return false; 2750 } 2751 2752 const char* typeA = command.GetArgumentAtIndex(0); 2753 ConstString typeCS(typeA); 2754 2755 if (!typeCS) 2756 { 2757 result.AppendError("empty typenames not allowed"); 2758 result.SetStatus(eReturnStatusFailed); 2759 return false; 2760 } 2761 2762 if (m_options.m_delete_all) 2763 { 2764 DataVisualization::Categories::LoopThrough(PerCategoryCallback, (void*)&typeCS); 2765 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2766 return result.Succeeded(); 2767 } 2768 2769 lldb::TypeCategoryImplSP category; 2770 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 2771 2772 bool delete_category = category->GetFilterNavigator()->Delete(typeCS); 2773 delete_category = category->GetRegexFilterNavigator()->Delete(typeCS) || delete_category; 2774 2775 if (delete_category) 2776 { 2777 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2778 return result.Succeeded(); 2779 } 2780 else 2781 { 2782 result.AppendErrorWithFormat ("no custom synthetic provider for %s.\n", typeA); 2783 result.SetStatus(eReturnStatusFailed); 2784 return false; 2785 } 2786 2787 } 2788 }; 2789 2790 OptionDefinition 2791 CommandObjectTypeFilterDelete::CommandOptions::g_option_table[] = 2792 { 2793 { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Delete from every category."}, 2794 { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Delete from given category."}, 2795 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 2796 }; 2797 2798 #ifndef LLDB_DISABLE_PYTHON 2799 2800 //------------------------------------------------------------------------- 2801 // CommandObjectTypeSynthDelete 2802 //------------------------------------------------------------------------- 2803 2804 class CommandObjectTypeSynthDelete : public CommandObject 2805 { 2806 private: 2807 class CommandOptions : public Options 2808 { 2809 public: 2810 2811 CommandOptions (CommandInterpreter &interpreter) : 2812 Options (interpreter) 2813 { 2814 } 2815 2816 virtual 2817 ~CommandOptions (){} 2818 2819 virtual Error 2820 SetOptionValue (uint32_t option_idx, const char *option_arg) 2821 { 2822 Error error; 2823 char short_option = (char) m_getopt_table[option_idx].val; 2824 2825 switch (short_option) 2826 { 2827 case 'a': 2828 m_delete_all = true; 2829 break; 2830 case 'w': 2831 m_category = std::string(option_arg); 2832 break; 2833 default: 2834 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2835 break; 2836 } 2837 2838 return error; 2839 } 2840 2841 void 2842 OptionParsingStarting () 2843 { 2844 m_delete_all = false; 2845 m_category = "default"; 2846 } 2847 2848 const OptionDefinition* 2849 GetDefinitions () 2850 { 2851 return g_option_table; 2852 } 2853 2854 // Options table: Required for subclasses of Options. 2855 2856 static OptionDefinition g_option_table[]; 2857 2858 // Instance variables to hold the values for command options. 2859 2860 bool m_delete_all; 2861 std::string m_category; 2862 2863 }; 2864 2865 CommandOptions m_options; 2866 2867 virtual Options * 2868 GetOptions () 2869 { 2870 return &m_options; 2871 } 2872 2873 static bool 2874 PerCategoryCallback(void* param, 2875 const lldb::TypeCategoryImplSP& cate) 2876 { 2877 ConstString* name = (ConstString*)param; 2878 return cate->Delete(*name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth); 2879 } 2880 2881 public: 2882 CommandObjectTypeSynthDelete (CommandInterpreter &interpreter) : 2883 CommandObject (interpreter, 2884 "type synthetic delete", 2885 "Delete an existing synthetic provider for a type.", 2886 NULL), m_options(interpreter) 2887 { 2888 CommandArgumentEntry type_arg; 2889 CommandArgumentData type_style_arg; 2890 2891 type_style_arg.arg_type = eArgTypeName; 2892 type_style_arg.arg_repetition = eArgRepeatPlain; 2893 2894 type_arg.push_back (type_style_arg); 2895 2896 m_arguments.push_back (type_arg); 2897 2898 } 2899 2900 ~CommandObjectTypeSynthDelete () 2901 { 2902 } 2903 2904 bool 2905 Execute (Args& command, CommandReturnObject &result) 2906 { 2907 const size_t argc = command.GetArgumentCount(); 2908 2909 if (argc != 1) 2910 { 2911 result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); 2912 result.SetStatus(eReturnStatusFailed); 2913 return false; 2914 } 2915 2916 const char* typeA = command.GetArgumentAtIndex(0); 2917 ConstString typeCS(typeA); 2918 2919 if (!typeCS) 2920 { 2921 result.AppendError("empty typenames not allowed"); 2922 result.SetStatus(eReturnStatusFailed); 2923 return false; 2924 } 2925 2926 if (m_options.m_delete_all) 2927 { 2928 DataVisualization::Categories::LoopThrough(PerCategoryCallback, (void*)&typeCS); 2929 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2930 return result.Succeeded(); 2931 } 2932 2933 lldb::TypeCategoryImplSP category; 2934 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 2935 2936 bool delete_category = category->GetSyntheticNavigator()->Delete(typeCS); 2937 delete_category = category->GetRegexSyntheticNavigator()->Delete(typeCS) || delete_category; 2938 2939 if (delete_category) 2940 { 2941 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2942 return result.Succeeded(); 2943 } 2944 else 2945 { 2946 result.AppendErrorWithFormat ("no custom synthetic provider for %s.\n", typeA); 2947 result.SetStatus(eReturnStatusFailed); 2948 return false; 2949 } 2950 2951 } 2952 }; 2953 2954 OptionDefinition 2955 CommandObjectTypeSynthDelete::CommandOptions::g_option_table[] = 2956 { 2957 { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Delete from every category."}, 2958 { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Delete from given category."}, 2959 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 2960 }; 2961 2962 #endif // #ifndef LLDB_DISABLE_PYTHON 2963 2964 //------------------------------------------------------------------------- 2965 // CommandObjectTypeFilterClear 2966 //------------------------------------------------------------------------- 2967 2968 class CommandObjectTypeFilterClear : public CommandObject 2969 { 2970 private: 2971 2972 class CommandOptions : public Options 2973 { 2974 public: 2975 2976 CommandOptions (CommandInterpreter &interpreter) : 2977 Options (interpreter) 2978 { 2979 } 2980 2981 virtual 2982 ~CommandOptions (){} 2983 2984 virtual Error 2985 SetOptionValue (uint32_t option_idx, const char *option_arg) 2986 { 2987 Error error; 2988 char short_option = (char) m_getopt_table[option_idx].val; 2989 2990 switch (short_option) 2991 { 2992 case 'a': 2993 m_delete_all = true; 2994 break; 2995 default: 2996 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2997 break; 2998 } 2999 3000 return error; 3001 } 3002 3003 void 3004 OptionParsingStarting () 3005 { 3006 m_delete_all = false; 3007 } 3008 3009 const OptionDefinition* 3010 GetDefinitions () 3011 { 3012 return g_option_table; 3013 } 3014 3015 // Options table: Required for subclasses of Options. 3016 3017 static OptionDefinition g_option_table[]; 3018 3019 // Instance variables to hold the values for command options. 3020 3021 bool m_delete_all; 3022 bool m_delete_named; 3023 }; 3024 3025 CommandOptions m_options; 3026 3027 virtual Options * 3028 GetOptions () 3029 { 3030 return &m_options; 3031 } 3032 3033 static bool 3034 PerCategoryCallback(void* param, 3035 const lldb::TypeCategoryImplSP& cate) 3036 { 3037 cate->Clear(eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter); 3038 return true; 3039 3040 } 3041 3042 public: 3043 CommandObjectTypeFilterClear (CommandInterpreter &interpreter) : 3044 CommandObject (interpreter, 3045 "type filter clear", 3046 "Delete all existing filters.", 3047 NULL), m_options(interpreter) 3048 { 3049 } 3050 3051 ~CommandObjectTypeFilterClear () 3052 { 3053 } 3054 3055 bool 3056 Execute (Args& command, CommandReturnObject &result) 3057 { 3058 3059 if (m_options.m_delete_all) 3060 DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL); 3061 3062 else 3063 { 3064 lldb::TypeCategoryImplSP category; 3065 if (command.GetArgumentCount() > 0) 3066 { 3067 const char* cat_name = command.GetArgumentAtIndex(0); 3068 ConstString cat_nameCS(cat_name); 3069 DataVisualization::Categories::GetCategory(cat_nameCS, category); 3070 } 3071 else 3072 DataVisualization::Categories::GetCategory(ConstString(NULL), category); 3073 category->GetFilterNavigator()->Clear(); 3074 category->GetRegexFilterNavigator()->Clear(); 3075 } 3076 3077 result.SetStatus(eReturnStatusSuccessFinishResult); 3078 return result.Succeeded(); 3079 } 3080 3081 }; 3082 3083 OptionDefinition 3084 CommandObjectTypeFilterClear::CommandOptions::g_option_table[] = 3085 { 3086 { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Clear every category."}, 3087 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 3088 }; 3089 3090 #ifndef LLDB_DISABLE_PYTHON 3091 //------------------------------------------------------------------------- 3092 // CommandObjectTypeSynthClear 3093 //------------------------------------------------------------------------- 3094 3095 class CommandObjectTypeSynthClear : public CommandObject 3096 { 3097 private: 3098 3099 class CommandOptions : public Options 3100 { 3101 public: 3102 3103 CommandOptions (CommandInterpreter &interpreter) : 3104 Options (interpreter) 3105 { 3106 } 3107 3108 virtual 3109 ~CommandOptions (){} 3110 3111 virtual Error 3112 SetOptionValue (uint32_t option_idx, const char *option_arg) 3113 { 3114 Error error; 3115 char short_option = (char) m_getopt_table[option_idx].val; 3116 3117 switch (short_option) 3118 { 3119 case 'a': 3120 m_delete_all = true; 3121 break; 3122 default: 3123 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 3124 break; 3125 } 3126 3127 return error; 3128 } 3129 3130 void 3131 OptionParsingStarting () 3132 { 3133 m_delete_all = false; 3134 } 3135 3136 const OptionDefinition* 3137 GetDefinitions () 3138 { 3139 return g_option_table; 3140 } 3141 3142 // Options table: Required for subclasses of Options. 3143 3144 static OptionDefinition g_option_table[]; 3145 3146 // Instance variables to hold the values for command options. 3147 3148 bool m_delete_all; 3149 bool m_delete_named; 3150 }; 3151 3152 CommandOptions m_options; 3153 3154 virtual Options * 3155 GetOptions () 3156 { 3157 return &m_options; 3158 } 3159 3160 static bool 3161 PerCategoryCallback(void* param, 3162 const lldb::TypeCategoryImplSP& cate) 3163 { 3164 cate->Clear(eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth); 3165 return true; 3166 3167 } 3168 3169 public: 3170 CommandObjectTypeSynthClear (CommandInterpreter &interpreter) : 3171 CommandObject (interpreter, 3172 "type synthetic clear", 3173 "Delete all existing synthetic providers.", 3174 NULL), m_options(interpreter) 3175 { 3176 } 3177 3178 ~CommandObjectTypeSynthClear () 3179 { 3180 } 3181 3182 bool 3183 Execute (Args& command, CommandReturnObject &result) 3184 { 3185 3186 if (m_options.m_delete_all) 3187 DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL); 3188 3189 else 3190 { 3191 lldb::TypeCategoryImplSP category; 3192 if (command.GetArgumentCount() > 0) 3193 { 3194 const char* cat_name = command.GetArgumentAtIndex(0); 3195 ConstString cat_nameCS(cat_name); 3196 DataVisualization::Categories::GetCategory(cat_nameCS, category); 3197 } 3198 else 3199 DataVisualization::Categories::GetCategory(ConstString(NULL), category); 3200 category->GetSyntheticNavigator()->Clear(); 3201 category->GetRegexSyntheticNavigator()->Clear(); 3202 } 3203 3204 result.SetStatus(eReturnStatusSuccessFinishResult); 3205 return result.Succeeded(); 3206 } 3207 3208 }; 3209 3210 OptionDefinition 3211 CommandObjectTypeSynthClear::CommandOptions::g_option_table[] = 3212 { 3213 { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Clear every category."}, 3214 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 3215 }; 3216 3217 3218 //------------------------------------------------------------------------- 3219 // TypeSynthAddInputReader 3220 //------------------------------------------------------------------------- 3221 3222 static const char *g_synth_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" 3223 "You must define a Python class with these methods:\n" 3224 " def __init__(self, valobj, dict):\n" 3225 " def num_children(self):\n" 3226 " def get_child_at_index(self, index):\n" 3227 " def get_child_index(self, name):\n" 3228 "Optionally, you can also define a method:\n" 3229 " def update(self):\n" 3230 "if your synthetic provider is holding on to any per-object state variables (currently, this is not implemented because of the way LLDB handles instances of SBValue and you should not rely on object persistence and per-object state)\n" 3231 "class synthProvider:"; 3232 3233 class TypeSynthAddInputReader : public InputReaderEZ 3234 { 3235 public: 3236 TypeSynthAddInputReader(Debugger& debugger) : 3237 InputReaderEZ(debugger) 3238 {} 3239 3240 virtual 3241 ~TypeSynthAddInputReader() 3242 { 3243 } 3244 3245 virtual void ActivateHandler(HandlerData& data) 3246 { 3247 StreamSP out_stream = data.GetOutStream(); 3248 bool batch_mode = data.GetBatchMode(); 3249 if (!batch_mode) 3250 { 3251 out_stream->Printf ("%s\n", g_synth_addreader_instructions); 3252 if (data.reader.GetPrompt()) 3253 out_stream->Printf ("%s", data.reader.GetPrompt()); 3254 out_stream->Flush(); 3255 } 3256 } 3257 3258 virtual void ReactivateHandler(HandlerData& data) 3259 { 3260 StreamSP out_stream = data.GetOutStream(); 3261 bool batch_mode = data.GetBatchMode(); 3262 if (data.reader.GetPrompt() && !batch_mode) 3263 { 3264 out_stream->Printf ("%s", data.reader.GetPrompt()); 3265 out_stream->Flush(); 3266 } 3267 } 3268 virtual void GotTokenHandler(HandlerData& data) 3269 { 3270 StreamSP out_stream = data.GetOutStream(); 3271 bool batch_mode = data.GetBatchMode(); 3272 if (data.bytes && data.bytes_len && data.baton) 3273 { 3274 ((SynthAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len); 3275 } 3276 if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode) 3277 { 3278 out_stream->Printf ("%s", data.reader.GetPrompt()); 3279 out_stream->Flush(); 3280 } 3281 } 3282 virtual void InterruptHandler(HandlerData& data) 3283 { 3284 StreamSP out_stream = data.GetOutStream(); 3285 bool batch_mode = data.GetBatchMode(); 3286 data.reader.SetIsDone (true); 3287 if (!batch_mode) 3288 { 3289 out_stream->Printf ("Warning: No command attached to breakpoint.\n"); 3290 out_stream->Flush(); 3291 } 3292 } 3293 virtual void EOFHandler(HandlerData& data) 3294 { 3295 data.reader.SetIsDone (true); 3296 } 3297 virtual void DoneHandler(HandlerData& data) 3298 { 3299 StreamSP out_stream = data.GetOutStream(); 3300 SynthAddOptions *options_ptr = ((SynthAddOptions*)data.baton); 3301 if (!options_ptr) 3302 { 3303 out_stream->Printf ("Internal error #1: no script attached.\n"); 3304 out_stream->Flush(); 3305 return; 3306 } 3307 3308 SynthAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope 3309 3310 ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 3311 if (!interpreter) 3312 { 3313 out_stream->Printf ("Internal error #2: no script attached.\n"); 3314 out_stream->Flush(); 3315 return; 3316 } 3317 std::string class_name_str; 3318 if (!interpreter->GenerateTypeSynthClass (options->m_user_source, 3319 class_name_str)) 3320 { 3321 out_stream->Printf ("Internal error #3: no script attached.\n"); 3322 out_stream->Flush(); 3323 return; 3324 } 3325 if (class_name_str.empty()) 3326 { 3327 out_stream->Printf ("Internal error #4: no script attached.\n"); 3328 out_stream->Flush(); 3329 return; 3330 } 3331 3332 // everything should be fine now, let's add the synth provider class 3333 3334 SyntheticChildrenSP synth_provider; 3335 synth_provider.reset(new TypeSyntheticImpl(SyntheticChildren::Flags().SetCascades(options->m_cascade). 3336 SetSkipPointers(options->m_skip_pointers). 3337 SetSkipReferences(options->m_skip_references), 3338 class_name_str.c_str())); 3339 3340 3341 lldb::TypeCategoryImplSP category; 3342 DataVisualization::Categories::GetCategory(ConstString(options->m_category.c_str()), category); 3343 3344 Error error; 3345 3346 for (size_t i = 0; i < options->m_target_types.GetSize(); i++) 3347 { 3348 const char *type_name = options->m_target_types.GetStringAtIndex(i); 3349 ConstString typeCS(type_name); 3350 if (typeCS) 3351 { 3352 if (!CommandObjectTypeSynthAdd::AddSynth(typeCS, 3353 synth_provider, 3354 options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth, 3355 options->m_category, 3356 &error)) 3357 { 3358 out_stream->Printf("%s\n", error.AsCString()); 3359 out_stream->Flush(); 3360 return; 3361 } 3362 } 3363 else 3364 { 3365 out_stream->Printf ("Internal error #6: no script attached.\n"); 3366 out_stream->Flush(); 3367 return; 3368 } 3369 } 3370 } 3371 3372 private: 3373 DISALLOW_COPY_AND_ASSIGN (TypeSynthAddInputReader); 3374 }; 3375 3376 void 3377 CommandObjectTypeSynthAdd::CollectPythonScript (SynthAddOptions *options, 3378 CommandReturnObject &result) 3379 { 3380 InputReaderSP reader_sp (new TypeSynthAddInputReader(m_interpreter.GetDebugger())); 3381 if (reader_sp && options) 3382 { 3383 3384 InputReaderEZ::InitializationParameters ipr; 3385 3386 Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt(" "))); 3387 if (err.Success()) 3388 { 3389 m_interpreter.GetDebugger().PushInputReader (reader_sp); 3390 result.SetStatus (eReturnStatusSuccessFinishNoResult); 3391 } 3392 else 3393 { 3394 result.AppendError (err.AsCString()); 3395 result.SetStatus (eReturnStatusFailed); 3396 } 3397 } 3398 else 3399 { 3400 result.AppendError("out of memory"); 3401 result.SetStatus (eReturnStatusFailed); 3402 } 3403 } 3404 3405 bool 3406 CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result) 3407 { 3408 SynthAddOptions *options = new SynthAddOptions ( m_options.m_skip_pointers, 3409 m_options.m_skip_references, 3410 m_options.m_cascade, 3411 m_options.m_regex, 3412 m_options.m_category); 3413 3414 const size_t argc = command.GetArgumentCount(); 3415 3416 for (size_t i = 0; i < argc; i++) 3417 { 3418 const char* typeA = command.GetArgumentAtIndex(i); 3419 if (typeA && *typeA) 3420 options->m_target_types << typeA; 3421 else 3422 { 3423 result.AppendError("empty typenames not allowed"); 3424 result.SetStatus(eReturnStatusFailed); 3425 return false; 3426 } 3427 } 3428 3429 CollectPythonScript(options,result); 3430 return result.Succeeded(); 3431 } 3432 3433 bool 3434 CommandObjectTypeSynthAdd::Execute_PythonClass (Args& command, CommandReturnObject &result) 3435 { 3436 const size_t argc = command.GetArgumentCount(); 3437 3438 if (argc < 1) 3439 { 3440 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 3441 result.SetStatus(eReturnStatusFailed); 3442 return false; 3443 } 3444 3445 if (m_options.m_class_name.empty() && !m_options.m_input_python) 3446 { 3447 result.AppendErrorWithFormat ("%s needs either a Python class name or -P to directly input Python code.\n", m_cmd_name.c_str()); 3448 result.SetStatus(eReturnStatusFailed); 3449 return false; 3450 } 3451 3452 SyntheticChildrenSP entry; 3453 3454 TypeSyntheticImpl* impl = new TypeSyntheticImpl(SyntheticChildren::Flags(). 3455 SetCascades(m_options.m_cascade). 3456 SetSkipPointers(m_options.m_skip_pointers). 3457 SetSkipReferences(m_options.m_skip_references), 3458 m_options.m_class_name.c_str()); 3459 3460 entry.reset(impl); 3461 3462 // now I have a valid provider, let's add it to every type 3463 3464 lldb::TypeCategoryImplSP category; 3465 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 3466 3467 Error error; 3468 3469 for (size_t i = 0; i < argc; i++) 3470 { 3471 const char* typeA = command.GetArgumentAtIndex(i); 3472 ConstString typeCS(typeA); 3473 if (typeCS) 3474 { 3475 if (!AddSynth(typeCS, 3476 entry, 3477 m_options.m_regex ? eRegexSynth : eRegularSynth, 3478 m_options.m_category, 3479 &error)) 3480 { 3481 result.AppendError(error.AsCString()); 3482 result.SetStatus(eReturnStatusFailed); 3483 return false; 3484 } 3485 } 3486 else 3487 { 3488 result.AppendError("empty typenames not allowed"); 3489 result.SetStatus(eReturnStatusFailed); 3490 return false; 3491 } 3492 } 3493 3494 result.SetStatus(eReturnStatusSuccessFinishNoResult); 3495 return result.Succeeded(); 3496 } 3497 3498 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) : 3499 CommandObject (interpreter, 3500 "type synthetic add", 3501 "Add a new synthetic provider for a type.", 3502 NULL), m_options (interpreter) 3503 { 3504 CommandArgumentEntry type_arg; 3505 CommandArgumentData type_style_arg; 3506 3507 type_style_arg.arg_type = eArgTypeName; 3508 type_style_arg.arg_repetition = eArgRepeatPlus; 3509 3510 type_arg.push_back (type_style_arg); 3511 3512 m_arguments.push_back (type_arg); 3513 3514 } 3515 3516 bool 3517 CommandObjectTypeSynthAdd::AddSynth(const ConstString& type_name, 3518 SyntheticChildrenSP entry, 3519 SynthFormatType type, 3520 std::string category_name, 3521 Error* error) 3522 { 3523 lldb::TypeCategoryImplSP category; 3524 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); 3525 3526 if (category->AnyMatches(type_name, 3527 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 3528 false)) 3529 { 3530 if (error) 3531 error->SetErrorStringWithFormat("cannot add synthetic for type %s when filter is defined in same category!", type_name.AsCString()); 3532 return false; 3533 } 3534 3535 if (type == eRegexSynth) 3536 { 3537 RegularExpressionSP typeRX(new RegularExpression()); 3538 if (!typeRX->Compile(type_name.GetCString())) 3539 { 3540 if (error) 3541 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 3542 return false; 3543 } 3544 3545 category->GetRegexSyntheticNavigator()->Delete(type_name); 3546 category->GetRegexSyntheticNavigator()->Add(typeRX, entry); 3547 3548 return true; 3549 } 3550 else 3551 { 3552 category->GetSyntheticNavigator()->Add(type_name, entry); 3553 return true; 3554 } 3555 } 3556 3557 bool 3558 CommandObjectTypeSynthAdd::Execute (Args& command, CommandReturnObject &result) 3559 { 3560 if (m_options.handwrite_python) 3561 return Execute_HandwritePython(command, result); 3562 else if (m_options.is_class_based) 3563 return Execute_PythonClass(command, result); 3564 else 3565 { 3566 result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line"); 3567 result.SetStatus(eReturnStatusFailed); 3568 return false; 3569 } 3570 } 3571 3572 OptionDefinition 3573 CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] = 3574 { 3575 { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, 3576 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 3577 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 3578 { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 3579 { LLDB_OPT_SET_2, false, "python-class", 'l', required_argument, NULL, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children."}, 3580 { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children."}, 3581 { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, 3582 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 3583 }; 3584 3585 #endif // #ifndef LLDB_DISABLE_PYTHON 3586 3587 class CommandObjectTypeFilterAdd : public CommandObject 3588 { 3589 3590 private: 3591 3592 class CommandOptions : public Options 3593 { 3594 typedef std::vector<std::string> option_vector; 3595 public: 3596 3597 CommandOptions (CommandInterpreter &interpreter) : 3598 Options (interpreter) 3599 { 3600 } 3601 3602 virtual 3603 ~CommandOptions (){} 3604 3605 virtual Error 3606 SetOptionValue (uint32_t option_idx, const char *option_arg) 3607 { 3608 Error error; 3609 char short_option = (char) m_getopt_table[option_idx].val; 3610 bool success; 3611 3612 switch (short_option) 3613 { 3614 case 'C': 3615 m_cascade = Args::StringToBoolean(option_arg, true, &success); 3616 if (!success) 3617 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg); 3618 break; 3619 case 'c': 3620 m_expr_paths.push_back(option_arg); 3621 has_child_list = true; 3622 break; 3623 case 'p': 3624 m_skip_pointers = true; 3625 break; 3626 case 'r': 3627 m_skip_references = true; 3628 break; 3629 case 'w': 3630 m_category = std::string(option_arg); 3631 break; 3632 case 'x': 3633 m_regex = true; 3634 break; 3635 default: 3636 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 3637 break; 3638 } 3639 3640 return error; 3641 } 3642 3643 void 3644 OptionParsingStarting () 3645 { 3646 m_cascade = true; 3647 m_skip_pointers = false; 3648 m_skip_references = false; 3649 m_category = "default"; 3650 m_expr_paths.clear(); 3651 has_child_list = false; 3652 m_regex = false; 3653 } 3654 3655 const OptionDefinition* 3656 GetDefinitions () 3657 { 3658 return g_option_table; 3659 } 3660 3661 // Options table: Required for subclasses of Options. 3662 3663 static OptionDefinition g_option_table[]; 3664 3665 // Instance variables to hold the values for command options. 3666 3667 bool m_cascade; 3668 bool m_skip_references; 3669 bool m_skip_pointers; 3670 bool m_input_python; 3671 option_vector m_expr_paths; 3672 std::string m_category; 3673 3674 bool has_child_list; 3675 3676 bool m_regex; 3677 3678 typedef option_vector::iterator ExpressionPathsIterator; 3679 }; 3680 3681 CommandOptions m_options; 3682 3683 virtual Options * 3684 GetOptions () 3685 { 3686 return &m_options; 3687 } 3688 3689 enum FilterFormatType 3690 { 3691 eRegularFilter, 3692 eRegexFilter 3693 }; 3694 3695 bool 3696 AddFilter(const ConstString& type_name, 3697 SyntheticChildrenSP entry, 3698 FilterFormatType type, 3699 std::string category_name, 3700 Error* error) 3701 { 3702 lldb::TypeCategoryImplSP category; 3703 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); 3704 3705 if (category->AnyMatches(type_name, 3706 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 3707 false)) 3708 { 3709 if (error) 3710 error->SetErrorStringWithFormat("cannot add filter for type %s when synthetic is defined in same category!", type_name.AsCString()); 3711 return false; 3712 } 3713 3714 if (type == eRegexFilter) 3715 { 3716 RegularExpressionSP typeRX(new RegularExpression()); 3717 if (!typeRX->Compile(type_name.GetCString())) 3718 { 3719 if (error) 3720 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 3721 return false; 3722 } 3723 3724 category->GetRegexFilterNavigator()->Delete(type_name); 3725 category->GetRegexFilterNavigator()->Add(typeRX, entry); 3726 3727 return true; 3728 } 3729 else 3730 { 3731 category->GetFilterNavigator()->Add(type_name, entry); 3732 return true; 3733 } 3734 } 3735 3736 3737 public: 3738 3739 CommandObjectTypeFilterAdd (CommandInterpreter &interpreter) : 3740 CommandObject (interpreter, 3741 "type filter add", 3742 "Add a new filter for a type.", 3743 NULL), 3744 m_options (interpreter) 3745 { 3746 CommandArgumentEntry type_arg; 3747 CommandArgumentData type_style_arg; 3748 3749 type_style_arg.arg_type = eArgTypeName; 3750 type_style_arg.arg_repetition = eArgRepeatPlus; 3751 3752 type_arg.push_back (type_style_arg); 3753 3754 m_arguments.push_back (type_arg); 3755 3756 SetHelpLong( 3757 "Some examples of using this command.\n" 3758 "We use as reference the following snippet of code:\n" 3759 "\n" 3760 "class Foo {;\n" 3761 " int a;\n" 3762 " int b;\n" 3763 " int c;\n" 3764 " int d;\n" 3765 " int e;\n" 3766 " int f;\n" 3767 " int g;\n" 3768 " int h;\n" 3769 " int i;\n" 3770 "} \n" 3771 "Typing:\n" 3772 "type filter add --child a -- child g Foo\n" 3773 "frame variable a_foo\n" 3774 "will produce an output where only a and b are displayed\n" 3775 "Other children of a_foo (b,c,d,e,f,h and i) are available by asking for them, as in:\n" 3776 "frame variable a_foo.b a_foo.c ... a_foo.i\n" 3777 "\n" 3778 "Use option --raw to frame variable prevails on the filter\n" 3779 "frame variable a_foo --raw\n" 3780 "shows all the children of a_foo (a thru i) as if no filter was defined\n" 3781 ); 3782 } 3783 3784 ~CommandObjectTypeFilterAdd () 3785 { 3786 } 3787 3788 bool 3789 Execute (Args& command, CommandReturnObject &result) 3790 { 3791 const size_t argc = command.GetArgumentCount(); 3792 3793 if (argc < 1) 3794 { 3795 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 3796 result.SetStatus(eReturnStatusFailed); 3797 return false; 3798 } 3799 3800 if (m_options.m_expr_paths.size() == 0) 3801 { 3802 result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str()); 3803 result.SetStatus(eReturnStatusFailed); 3804 return false; 3805 } 3806 3807 SyntheticChildrenSP entry; 3808 3809 TypeFilterImpl* impl = new TypeFilterImpl(SyntheticChildren::Flags().SetCascades(m_options.m_cascade). 3810 SetSkipPointers(m_options.m_skip_pointers). 3811 SetSkipReferences(m_options.m_skip_references)); 3812 3813 entry.reset(impl); 3814 3815 // go through the expression paths 3816 CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end(); 3817 3818 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++) 3819 impl->AddExpressionPath(*begin); 3820 3821 3822 // now I have a valid provider, let's add it to every type 3823 3824 lldb::TypeCategoryImplSP category; 3825 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 3826 3827 Error error; 3828 3829 for (size_t i = 0; i < argc; i++) 3830 { 3831 const char* typeA = command.GetArgumentAtIndex(i); 3832 ConstString typeCS(typeA); 3833 if (typeCS) 3834 { 3835 if (!AddFilter(typeCS, 3836 entry, 3837 m_options.m_regex ? eRegexFilter : eRegularFilter, 3838 m_options.m_category, 3839 &error)) 3840 { 3841 result.AppendError(error.AsCString()); 3842 result.SetStatus(eReturnStatusFailed); 3843 return false; 3844 } 3845 } 3846 else 3847 { 3848 result.AppendError("empty typenames not allowed"); 3849 result.SetStatus(eReturnStatusFailed); 3850 return false; 3851 } 3852 } 3853 3854 result.SetStatus(eReturnStatusSuccessFinishNoResult); 3855 return result.Succeeded(); 3856 } 3857 3858 }; 3859 3860 OptionDefinition 3861 CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] = 3862 { 3863 { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, 3864 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 3865 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 3866 { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 3867 { LLDB_OPT_SET_ALL, false, "child", 'c', required_argument, NULL, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view."}, 3868 { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, 3869 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 3870 }; 3871 3872 class CommandObjectTypeFormat : public CommandObjectMultiword 3873 { 3874 public: 3875 CommandObjectTypeFormat (CommandInterpreter &interpreter) : 3876 CommandObjectMultiword (interpreter, 3877 "type format", 3878 "A set of commands for editing variable value display options", 3879 "type format [<sub-command-options>] ") 3880 { 3881 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter))); 3882 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFormatClear (interpreter))); 3883 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter))); 3884 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFormatList (interpreter))); 3885 } 3886 3887 3888 ~CommandObjectTypeFormat () 3889 { 3890 } 3891 }; 3892 3893 #ifndef LLDB_DISABLE_PYTHON 3894 3895 class CommandObjectTypeSynth : public CommandObjectMultiword 3896 { 3897 public: 3898 CommandObjectTypeSynth (CommandInterpreter &interpreter) : 3899 CommandObjectMultiword (interpreter, 3900 "type synthetic", 3901 "A set of commands for operating on synthetic type representations", 3902 "type synthetic [<sub-command-options>] ") 3903 { 3904 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSynthAdd (interpreter))); 3905 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSynthClear (interpreter))); 3906 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSynthDelete (interpreter))); 3907 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSynthList (interpreter))); 3908 } 3909 3910 3911 ~CommandObjectTypeSynth () 3912 { 3913 } 3914 }; 3915 3916 #endif // #ifndef LLDB_DISABLE_PYTHON 3917 3918 class CommandObjectTypeFilter : public CommandObjectMultiword 3919 { 3920 public: 3921 CommandObjectTypeFilter (CommandInterpreter &interpreter) : 3922 CommandObjectMultiword (interpreter, 3923 "type filter", 3924 "A set of commands for operating on type filters", 3925 "type synthetic [<sub-command-options>] ") 3926 { 3927 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeFilterAdd (interpreter))); 3928 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFilterClear (interpreter))); 3929 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFilterDelete (interpreter))); 3930 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFilterList (interpreter))); 3931 } 3932 3933 3934 ~CommandObjectTypeFilter () 3935 { 3936 } 3937 }; 3938 3939 class CommandObjectTypeCategory : public CommandObjectMultiword 3940 { 3941 public: 3942 CommandObjectTypeCategory (CommandInterpreter &interpreter) : 3943 CommandObjectMultiword (interpreter, 3944 "type category", 3945 "A set of commands for operating on categories", 3946 "type category [<sub-command-options>] ") 3947 { 3948 LoadSubCommand ("enable", CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter))); 3949 LoadSubCommand ("disable", CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter))); 3950 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter))); 3951 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeCategoryList (interpreter))); 3952 } 3953 3954 3955 ~CommandObjectTypeCategory () 3956 { 3957 } 3958 }; 3959 3960 class CommandObjectTypeSummary : public CommandObjectMultiword 3961 { 3962 public: 3963 CommandObjectTypeSummary (CommandInterpreter &interpreter) : 3964 CommandObjectMultiword (interpreter, 3965 "type summary", 3966 "A set of commands for editing variable summary display options", 3967 "type summary [<sub-command-options>] ") 3968 { 3969 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter))); 3970 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter))); 3971 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter))); 3972 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); 3973 } 3974 3975 3976 ~CommandObjectTypeSummary () 3977 { 3978 } 3979 }; 3980 3981 //------------------------------------------------------------------------- 3982 // CommandObjectType 3983 //------------------------------------------------------------------------- 3984 3985 CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) : 3986 CommandObjectMultiword (interpreter, 3987 "type", 3988 "A set of commands for operating on the type system", 3989 "type [<sub-command-options>]") 3990 { 3991 LoadSubCommand ("category", CommandObjectSP (new CommandObjectTypeCategory (interpreter))); 3992 LoadSubCommand ("filter", CommandObjectSP (new CommandObjectTypeFilter (interpreter))); 3993 LoadSubCommand ("format", CommandObjectSP (new CommandObjectTypeFormat (interpreter))); 3994 LoadSubCommand ("summary", CommandObjectSP (new CommandObjectTypeSummary (interpreter))); 3995 #ifndef LLDB_DISABLE_PYTHON 3996 LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter))); 3997 #endif 3998 } 3999 4000 4001 CommandObjectType::~CommandObjectType () 4002 { 4003 } 4004 4005 4006