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