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