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/DataVisualization.h" 21 #include "lldb/Core/ConstString.h" 22 #include "lldb/Core/Debugger.h" 23 #include "lldb/Core/InputReaderEZ.h" 24 #include "lldb/Core/RegularExpression.h" 25 #include "lldb/Core/State.h" 26 #include "lldb/Core/StringList.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 error #1: no script attached.\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 ("Internal error #2: no script attached.\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 ("Internal error #3: no script attached.\n"); 840 out_stream->Flush(); 841 return; 842 } 843 if (funct_name_str.empty()) 844 { 845 out_stream->Printf ("Internal error #4: no script attached.\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 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 1041 if (!interpreter) 1042 { 1043 result.AppendError ("Internal error #1N: no script attached.\n"); 1044 result.SetStatus (eReturnStatusFailed); 1045 return false; 1046 } 1047 const char *funct_name = m_options.m_python_function.c_str(); 1048 if (!funct_name || !funct_name[0]) 1049 { 1050 result.AppendError ("Internal error #2N: no script attached.\n"); 1051 result.SetStatus (eReturnStatusFailed); 1052 return false; 1053 } 1054 1055 std::string code = (" " + m_options.m_python_function + "(valobj,internal_dict)"); 1056 1057 script_format.reset(new ScriptSummaryFormat(m_options.m_flags, 1058 funct_name, 1059 code.c_str())); 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 ("Internal error #1Q: no script attached.\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 ("Internal error #2Q: no script attached.\n"); 1077 result.SetStatus (eReturnStatusFailed); 1078 return false; 1079 } 1080 if (funct_name_str.empty()) 1081 { 1082 result.AppendError ("Internal error #3Q: no script attached.\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"), CategoryMap::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, CategoryMap::Default); 1976 } 1977 } 1978 DataVisualization::Categories::Enable(ConstString("system"), CategoryMap::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 error #1: no script attached.\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 ("Internal error #2: no script attached.\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 ("Internal error #3: no script attached.\n"); 3375 out_stream->Flush(); 3376 return; 3377 } 3378 if (class_name_str.empty()) 3379 { 3380 out_stream->Printf ("Internal error #4: no script attached.\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 TypeSyntheticImpl(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 ("Internal error #6: no script attached.\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 TypeSyntheticImpl* impl = new TypeSyntheticImpl(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 // now I have a valid provider, let's add it to every type 3516 3517 lldb::TypeCategoryImplSP category; 3518 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 3519 3520 Error error; 3521 3522 for (size_t i = 0; i < argc; i++) 3523 { 3524 const char* typeA = command.GetArgumentAtIndex(i); 3525 ConstString typeCS(typeA); 3526 if (typeCS) 3527 { 3528 if (!AddSynth(typeCS, 3529 entry, 3530 m_options.m_regex ? eRegexSynth : eRegularSynth, 3531 m_options.m_category, 3532 &error)) 3533 { 3534 result.AppendError(error.AsCString()); 3535 result.SetStatus(eReturnStatusFailed); 3536 return false; 3537 } 3538 } 3539 else 3540 { 3541 result.AppendError("empty typenames not allowed"); 3542 result.SetStatus(eReturnStatusFailed); 3543 return false; 3544 } 3545 } 3546 3547 result.SetStatus(eReturnStatusSuccessFinishNoResult); 3548 return result.Succeeded(); 3549 } 3550 3551 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) : 3552 CommandObjectParsed (interpreter, 3553 "type synthetic add", 3554 "Add a new synthetic provider for a type.", 3555 NULL), 3556 m_options (interpreter) 3557 { 3558 CommandArgumentEntry type_arg; 3559 CommandArgumentData type_style_arg; 3560 3561 type_style_arg.arg_type = eArgTypeName; 3562 type_style_arg.arg_repetition = eArgRepeatPlus; 3563 3564 type_arg.push_back (type_style_arg); 3565 3566 m_arguments.push_back (type_arg); 3567 3568 } 3569 3570 bool 3571 CommandObjectTypeSynthAdd::AddSynth(const ConstString& type_name, 3572 SyntheticChildrenSP entry, 3573 SynthFormatType type, 3574 std::string category_name, 3575 Error* error) 3576 { 3577 lldb::TypeCategoryImplSP category; 3578 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); 3579 3580 if (category->AnyMatches(type_name, 3581 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 3582 false)) 3583 { 3584 if (error) 3585 error->SetErrorStringWithFormat("cannot add synthetic for type %s when filter is defined in same category!", type_name.AsCString()); 3586 return false; 3587 } 3588 3589 if (type == eRegexSynth) 3590 { 3591 RegularExpressionSP typeRX(new RegularExpression()); 3592 if (!typeRX->Compile(type_name.GetCString())) 3593 { 3594 if (error) 3595 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 3596 return false; 3597 } 3598 3599 category->GetRegexSyntheticNavigator()->Delete(type_name); 3600 category->GetRegexSyntheticNavigator()->Add(typeRX, entry); 3601 3602 return true; 3603 } 3604 else 3605 { 3606 category->GetSyntheticNavigator()->Add(type_name, entry); 3607 return true; 3608 } 3609 } 3610 3611 bool 3612 CommandObjectTypeSynthAdd::DoExecute (Args& command, CommandReturnObject &result) 3613 { 3614 if (m_options.handwrite_python) 3615 return Execute_HandwritePython(command, result); 3616 else if (m_options.is_class_based) 3617 return Execute_PythonClass(command, result); 3618 else 3619 { 3620 result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line"); 3621 result.SetStatus(eReturnStatusFailed); 3622 return false; 3623 } 3624 } 3625 3626 OptionDefinition 3627 CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] = 3628 { 3629 { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, 3630 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 3631 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 3632 { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 3633 { LLDB_OPT_SET_2, false, "python-class", 'l', required_argument, NULL, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children."}, 3634 { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children."}, 3635 { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, 3636 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 3637 }; 3638 3639 #endif // #ifndef LLDB_DISABLE_PYTHON 3640 3641 class CommandObjectTypeFilterAdd : public CommandObjectParsed 3642 { 3643 3644 private: 3645 3646 class CommandOptions : public Options 3647 { 3648 typedef std::vector<std::string> option_vector; 3649 public: 3650 3651 CommandOptions (CommandInterpreter &interpreter) : 3652 Options (interpreter) 3653 { 3654 } 3655 3656 virtual 3657 ~CommandOptions (){} 3658 3659 virtual Error 3660 SetOptionValue (uint32_t option_idx, const char *option_arg) 3661 { 3662 Error error; 3663 const int short_option = m_getopt_table[option_idx].val; 3664 bool success; 3665 3666 switch (short_option) 3667 { 3668 case 'C': 3669 m_cascade = Args::StringToBoolean(option_arg, true, &success); 3670 if (!success) 3671 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg); 3672 break; 3673 case 'c': 3674 m_expr_paths.push_back(option_arg); 3675 has_child_list = true; 3676 break; 3677 case 'p': 3678 m_skip_pointers = true; 3679 break; 3680 case 'r': 3681 m_skip_references = true; 3682 break; 3683 case 'w': 3684 m_category = std::string(option_arg); 3685 break; 3686 case 'x': 3687 m_regex = true; 3688 break; 3689 default: 3690 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 3691 break; 3692 } 3693 3694 return error; 3695 } 3696 3697 void 3698 OptionParsingStarting () 3699 { 3700 m_cascade = true; 3701 m_skip_pointers = false; 3702 m_skip_references = false; 3703 m_category = "default"; 3704 m_expr_paths.clear(); 3705 has_child_list = false; 3706 m_regex = false; 3707 } 3708 3709 const OptionDefinition* 3710 GetDefinitions () 3711 { 3712 return g_option_table; 3713 } 3714 3715 // Options table: Required for subclasses of Options. 3716 3717 static OptionDefinition g_option_table[]; 3718 3719 // Instance variables to hold the values for command options. 3720 3721 bool m_cascade; 3722 bool m_skip_references; 3723 bool m_skip_pointers; 3724 bool m_input_python; 3725 option_vector m_expr_paths; 3726 std::string m_category; 3727 3728 bool has_child_list; 3729 3730 bool m_regex; 3731 3732 typedef option_vector::iterator ExpressionPathsIterator; 3733 }; 3734 3735 CommandOptions m_options; 3736 3737 virtual Options * 3738 GetOptions () 3739 { 3740 return &m_options; 3741 } 3742 3743 enum FilterFormatType 3744 { 3745 eRegularFilter, 3746 eRegexFilter 3747 }; 3748 3749 bool 3750 AddFilter(const ConstString& type_name, 3751 SyntheticChildrenSP entry, 3752 FilterFormatType type, 3753 std::string category_name, 3754 Error* error) 3755 { 3756 lldb::TypeCategoryImplSP category; 3757 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); 3758 3759 if (category->AnyMatches(type_name, 3760 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 3761 false)) 3762 { 3763 if (error) 3764 error->SetErrorStringWithFormat("cannot add filter for type %s when synthetic is defined in same category!", type_name.AsCString()); 3765 return false; 3766 } 3767 3768 if (type == eRegexFilter) 3769 { 3770 RegularExpressionSP typeRX(new RegularExpression()); 3771 if (!typeRX->Compile(type_name.GetCString())) 3772 { 3773 if (error) 3774 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 3775 return false; 3776 } 3777 3778 category->GetRegexFilterNavigator()->Delete(type_name); 3779 category->GetRegexFilterNavigator()->Add(typeRX, entry); 3780 3781 return true; 3782 } 3783 else 3784 { 3785 category->GetFilterNavigator()->Add(type_name, entry); 3786 return true; 3787 } 3788 } 3789 3790 3791 public: 3792 3793 CommandObjectTypeFilterAdd (CommandInterpreter &interpreter) : 3794 CommandObjectParsed (interpreter, 3795 "type filter add", 3796 "Add a new filter for a type.", 3797 NULL), 3798 m_options (interpreter) 3799 { 3800 CommandArgumentEntry type_arg; 3801 CommandArgumentData type_style_arg; 3802 3803 type_style_arg.arg_type = eArgTypeName; 3804 type_style_arg.arg_repetition = eArgRepeatPlus; 3805 3806 type_arg.push_back (type_style_arg); 3807 3808 m_arguments.push_back (type_arg); 3809 3810 SetHelpLong( 3811 "Some examples of using this command.\n" 3812 "We use as reference the following snippet of code:\n" 3813 "\n" 3814 "class Foo {;\n" 3815 " int a;\n" 3816 " int b;\n" 3817 " int c;\n" 3818 " int d;\n" 3819 " int e;\n" 3820 " int f;\n" 3821 " int g;\n" 3822 " int h;\n" 3823 " int i;\n" 3824 "} \n" 3825 "Typing:\n" 3826 "type filter add --child a --child g Foo\n" 3827 "frame variable a_foo\n" 3828 "will produce an output where only a and g are displayed\n" 3829 "Other children of a_foo (b,c,d,e,f,h and i) are available by asking for them, as in:\n" 3830 "frame variable a_foo.b a_foo.c ... a_foo.i\n" 3831 "\n" 3832 "Use option --raw to frame variable prevails on the filter\n" 3833 "frame variable a_foo --raw\n" 3834 "shows all the children of a_foo (a thru i) as if no filter was defined\n" 3835 ); 3836 } 3837 3838 ~CommandObjectTypeFilterAdd () 3839 { 3840 } 3841 3842 protected: 3843 bool 3844 DoExecute (Args& command, CommandReturnObject &result) 3845 { 3846 const size_t argc = command.GetArgumentCount(); 3847 3848 if (argc < 1) 3849 { 3850 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 3851 result.SetStatus(eReturnStatusFailed); 3852 return false; 3853 } 3854 3855 if (m_options.m_expr_paths.size() == 0) 3856 { 3857 result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str()); 3858 result.SetStatus(eReturnStatusFailed); 3859 return false; 3860 } 3861 3862 SyntheticChildrenSP entry; 3863 3864 TypeFilterImpl* impl = new TypeFilterImpl(SyntheticChildren::Flags().SetCascades(m_options.m_cascade). 3865 SetSkipPointers(m_options.m_skip_pointers). 3866 SetSkipReferences(m_options.m_skip_references)); 3867 3868 entry.reset(impl); 3869 3870 // go through the expression paths 3871 CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end(); 3872 3873 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++) 3874 impl->AddExpressionPath(*begin); 3875 3876 3877 // now I have a valid provider, let's add it to every type 3878 3879 lldb::TypeCategoryImplSP category; 3880 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 3881 3882 Error error; 3883 3884 for (size_t i = 0; i < argc; i++) 3885 { 3886 const char* typeA = command.GetArgumentAtIndex(i); 3887 ConstString typeCS(typeA); 3888 if (typeCS) 3889 { 3890 if (!AddFilter(typeCS, 3891 entry, 3892 m_options.m_regex ? eRegexFilter : eRegularFilter, 3893 m_options.m_category, 3894 &error)) 3895 { 3896 result.AppendError(error.AsCString()); 3897 result.SetStatus(eReturnStatusFailed); 3898 return false; 3899 } 3900 } 3901 else 3902 { 3903 result.AppendError("empty typenames not allowed"); 3904 result.SetStatus(eReturnStatusFailed); 3905 return false; 3906 } 3907 } 3908 3909 result.SetStatus(eReturnStatusSuccessFinishNoResult); 3910 return result.Succeeded(); 3911 } 3912 3913 }; 3914 3915 OptionDefinition 3916 CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] = 3917 { 3918 { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, 3919 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 3920 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 3921 { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 3922 { LLDB_OPT_SET_ALL, false, "child", 'c', required_argument, NULL, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view."}, 3923 { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, 3924 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 3925 }; 3926 3927 class CommandObjectTypeFormat : public CommandObjectMultiword 3928 { 3929 public: 3930 CommandObjectTypeFormat (CommandInterpreter &interpreter) : 3931 CommandObjectMultiword (interpreter, 3932 "type format", 3933 "A set of commands for editing variable value display options", 3934 "type format [<sub-command-options>] ") 3935 { 3936 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter))); 3937 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFormatClear (interpreter))); 3938 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter))); 3939 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFormatList (interpreter))); 3940 } 3941 3942 3943 ~CommandObjectTypeFormat () 3944 { 3945 } 3946 }; 3947 3948 #ifndef LLDB_DISABLE_PYTHON 3949 3950 class CommandObjectTypeSynth : public CommandObjectMultiword 3951 { 3952 public: 3953 CommandObjectTypeSynth (CommandInterpreter &interpreter) : 3954 CommandObjectMultiword (interpreter, 3955 "type synthetic", 3956 "A set of commands for operating on synthetic type representations", 3957 "type synthetic [<sub-command-options>] ") 3958 { 3959 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSynthAdd (interpreter))); 3960 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSynthClear (interpreter))); 3961 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSynthDelete (interpreter))); 3962 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSynthList (interpreter))); 3963 } 3964 3965 3966 ~CommandObjectTypeSynth () 3967 { 3968 } 3969 }; 3970 3971 #endif // #ifndef LLDB_DISABLE_PYTHON 3972 3973 class CommandObjectTypeFilter : public CommandObjectMultiword 3974 { 3975 public: 3976 CommandObjectTypeFilter (CommandInterpreter &interpreter) : 3977 CommandObjectMultiword (interpreter, 3978 "type filter", 3979 "A set of commands for operating on type filters", 3980 "type synthetic [<sub-command-options>] ") 3981 { 3982 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeFilterAdd (interpreter))); 3983 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFilterClear (interpreter))); 3984 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFilterDelete (interpreter))); 3985 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFilterList (interpreter))); 3986 } 3987 3988 3989 ~CommandObjectTypeFilter () 3990 { 3991 } 3992 }; 3993 3994 class CommandObjectTypeCategory : public CommandObjectMultiword 3995 { 3996 public: 3997 CommandObjectTypeCategory (CommandInterpreter &interpreter) : 3998 CommandObjectMultiword (interpreter, 3999 "type category", 4000 "A set of commands for operating on categories", 4001 "type category [<sub-command-options>] ") 4002 { 4003 LoadSubCommand ("enable", CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter))); 4004 LoadSubCommand ("disable", CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter))); 4005 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter))); 4006 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeCategoryList (interpreter))); 4007 } 4008 4009 4010 ~CommandObjectTypeCategory () 4011 { 4012 } 4013 }; 4014 4015 class CommandObjectTypeSummary : public CommandObjectMultiword 4016 { 4017 public: 4018 CommandObjectTypeSummary (CommandInterpreter &interpreter) : 4019 CommandObjectMultiword (interpreter, 4020 "type summary", 4021 "A set of commands for editing variable summary display options", 4022 "type summary [<sub-command-options>] ") 4023 { 4024 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter))); 4025 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter))); 4026 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter))); 4027 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); 4028 } 4029 4030 4031 ~CommandObjectTypeSummary () 4032 { 4033 } 4034 }; 4035 4036 //------------------------------------------------------------------------- 4037 // CommandObjectType 4038 //------------------------------------------------------------------------- 4039 4040 CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) : 4041 CommandObjectMultiword (interpreter, 4042 "type", 4043 "A set of commands for operating on the type system", 4044 "type [<sub-command-options>]") 4045 { 4046 LoadSubCommand ("category", CommandObjectSP (new CommandObjectTypeCategory (interpreter))); 4047 LoadSubCommand ("filter", CommandObjectSP (new CommandObjectTypeFilter (interpreter))); 4048 LoadSubCommand ("format", CommandObjectSP (new CommandObjectTypeFormat (interpreter))); 4049 LoadSubCommand ("summary", CommandObjectSP (new CommandObjectTypeSummary (interpreter))); 4050 #ifndef LLDB_DISABLE_PYTHON 4051 LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter))); 4052 #endif 4053 } 4054 4055 4056 CommandObjectType::~CommandObjectType () 4057 { 4058 } 4059 4060 4061