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