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 else 1193 { 1194 result.AppendError("added to types, but not given a name"); 1195 result.SetStatus(eReturnStatusFailed); 1196 return false; 1197 } 1198 1199 return result.Succeeded(); 1200 } 1201 1202 #endif 1203 1204 1205 bool 1206 CommandObjectTypeSummaryAdd::Execute_StringSummary (Args& command, CommandReturnObject &result) 1207 { 1208 const size_t argc = command.GetArgumentCount(); 1209 1210 if (argc < 1 && !m_options.m_name) 1211 { 1212 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 1213 result.SetStatus(eReturnStatusFailed); 1214 return false; 1215 } 1216 1217 if (!m_options.m_one_liner && m_options.m_format_string.empty()) 1218 { 1219 result.AppendError("empty summary strings not allowed"); 1220 result.SetStatus(eReturnStatusFailed); 1221 return false; 1222 } 1223 1224 const char* format_cstr = (m_options.m_one_liner ? "" : m_options.m_format_string.c_str()); 1225 1226 // ${var%S} is an endless recursion, prevent it 1227 if (strcmp(format_cstr, "${var%S}") == 0) 1228 { 1229 result.AppendError("recursive summary not allowed"); 1230 result.SetStatus(eReturnStatusFailed); 1231 return false; 1232 } 1233 1234 Error error; 1235 1236 lldb::SummaryFormatSP entry(new StringSummaryFormat(m_options.m_cascade, 1237 m_options.m_skip_pointers, 1238 m_options.m_skip_references, 1239 m_options.m_no_children, 1240 m_options.m_no_value, 1241 m_options.m_one_liner, 1242 format_cstr)); 1243 1244 if (error.Fail()) 1245 { 1246 result.AppendError(error.AsCString()); 1247 result.SetStatus(eReturnStatusFailed); 1248 return false; 1249 } 1250 1251 // now I have a valid format, let's add it to every type 1252 1253 for (size_t i = 0; i < argc; i++) 1254 { 1255 const char* typeA = command.GetArgumentAtIndex(i); 1256 if (!typeA || typeA[0] == '\0') 1257 { 1258 result.AppendError("empty typenames not allowed"); 1259 result.SetStatus(eReturnStatusFailed); 1260 return false; 1261 } 1262 ConstString typeCS(typeA); 1263 1264 AddSummary(typeCS, 1265 entry, 1266 (m_options.m_regex ? eRegexSummary : eRegularSummary), 1267 m_options.m_category, 1268 &error); 1269 1270 if (error.Fail()) 1271 { 1272 result.AppendError(error.AsCString()); 1273 result.SetStatus(eReturnStatusFailed); 1274 return false; 1275 } 1276 } 1277 1278 if (m_options.m_name) 1279 { 1280 AddSummary(m_options.m_name, entry, eNamedSummary, m_options.m_category, &error); 1281 if (error.Fail()) 1282 { 1283 result.AppendError(error.AsCString()); 1284 result.AppendError("added to types, but not given a name"); 1285 result.SetStatus(eReturnStatusFailed); 1286 return false; 1287 } 1288 } 1289 else 1290 { 1291 result.AppendError("added to types, but not given a name"); 1292 result.SetStatus(eReturnStatusFailed); 1293 return false; 1294 } 1295 1296 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1297 return result.Succeeded(); 1298 } 1299 1300 CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter) : 1301 CommandObject (interpreter, 1302 "type summary add", 1303 "Add a new summary style for a type.", 1304 NULL), m_options (interpreter) 1305 { 1306 CommandArgumentEntry type_arg; 1307 CommandArgumentData type_style_arg; 1308 1309 type_style_arg.arg_type = eArgTypeName; 1310 type_style_arg.arg_repetition = eArgRepeatPlus; 1311 1312 type_arg.push_back (type_style_arg); 1313 1314 m_arguments.push_back (type_arg); 1315 1316 SetHelpLong( 1317 "Some examples of using this command.\n" 1318 "We use as reference the following snippet of code:\n" 1319 "struct JustADemo\n" 1320 "{\n" 1321 "int* ptr;\n" 1322 "float value;\n" 1323 "JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}\n" 1324 "};\n" 1325 "JustADemo object(42,3.14);\n" 1326 "struct AnotherDemo : public JustADemo\n" 1327 "{\n" 1328 "uint8_t byte;\n" 1329 "AnotherDemo(uint8_t b = 'E', int p = 1, float v = 0.1) : JustADemo(p,v), byte(b) {}\n" 1330 "};\n" 1331 "AnotherDemo *another_object = new AnotherDemo('E',42,3.14);\n" 1332 "\n" 1333 "type summary add --summary-string \"the answer is ${*var.ptr}\" JustADemo\n" 1334 "when typing frame variable object you will get \"the answer is 42\"\n" 1335 "type summary add --summary-string \"the answer is ${*var.ptr}, and the question is ${var.value}\" JustADemo\n" 1336 "when typing frame variable object you will get \"the answer is 42 and the question is 3.14\"\n" 1337 "\n" 1338 "Alternatively, you could also say\n" 1339 "type summary add --summary-string \"${var%V} -> ${*var}\" \"int *\"\n" 1340 "and replace the above summary string with\n" 1341 "type summary add --summary-string \"the answer is ${var.ptr}, and the question is ${var.value}\" JustADemo\n" 1342 "to obtain a similar result\n" 1343 "\n" 1344 "To add a summary valid for both JustADemo and AnotherDemo you can use the scoping operator, as in:\n" 1345 "type summary add --summary-string \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes\n" 1346 "\n" 1347 "This will be used for both variables of type JustADemo and AnotherDemo. To prevent this, change the -C to read -C no\n" 1348 "If you do not want pointers to be shown using that summary, you can use the -p option, as in:\n" 1349 "type summary add --summary-string \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes -p\n" 1350 "A similar option -r exists for references.\n" 1351 "\n" 1352 "If you simply want a one-line summary of the content of your variable, without typing an explicit string to that effect\n" 1353 "you can use the -c option, without giving any summary string:\n" 1354 "type summary add -c JustADemo\n" 1355 "frame variable object\n" 1356 "the output being similar to (ptr=0xsomeaddress, value=3.14)\n" 1357 "\n" 1358 "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" 1359 "type summary add -e --summary-string \"*ptr = ${*var.ptr}\" JustADemo\n" 1360 "Here the value of the int* is displayed, followed by the standard LLDB sequence of children objects, one per line.\n" 1361 "to get an output like:\n" 1362 "\n" 1363 "*ptr = 42 {\n" 1364 " ptr = 0xsomeaddress\n" 1365 " value = 3.14\n" 1366 "}\n" 1367 "\n" 1368 "You can also add Python summaries, in which case you will use lldb public API to gather information from your variables" 1369 "and elaborate them to a meaningful summary inside a script written in Python. The variable object will be passed to your" 1370 "script as an SBValue object. The following example might help you when starting to use the Python summaries feature:\n" 1371 "type summary add JustADemo -o \"value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();\"\n" 1372 "If you prefer to type your scripts on multiple lines, you will use the -P option and then type your script, ending it with " 1373 "the word DONE on a line by itself to mark you're finished editing your code:\n" 1374 "(lldb)type summary add JustADemo -P\n" 1375 " value = valobj.GetChildMemberWithName('value');\n" 1376 " return 'My value is ' + value.GetValue();\n" 1377 "DONE\n" 1378 "(lldb) <-- type further LLDB commands here\n" 1379 ); 1380 } 1381 1382 bool 1383 CommandObjectTypeSummaryAdd::Execute (Args& command, CommandReturnObject &result) 1384 { 1385 if (m_options.m_is_add_script) 1386 { 1387 #ifndef LLDB_DISABLE_PYTHON 1388 return Execute_ScriptSummary(command, result); 1389 #else 1390 result.AppendError ("python is disabled"); 1391 result.SetStatus(eReturnStatusFailed); 1392 return false; 1393 #endif 1394 } 1395 1396 return Execute_StringSummary(command, result); 1397 } 1398 1399 bool 1400 CommandObjectTypeSummaryAdd::AddSummary(const ConstString& type_name, 1401 SummaryFormatSP entry, 1402 SummaryFormatType type, 1403 std::string category_name, 1404 Error* error) 1405 { 1406 lldb::FormatCategorySP category; 1407 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); 1408 1409 if (type == eRegexSummary) 1410 { 1411 RegularExpressionSP typeRX(new RegularExpression()); 1412 if (!typeRX->Compile(type_name.GetCString())) 1413 { 1414 if (error) 1415 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 1416 return false; 1417 } 1418 1419 category->GetRegexSummaryNavigator()->Delete(type_name); 1420 category->GetRegexSummaryNavigator()->Add(typeRX, entry); 1421 1422 return true; 1423 } 1424 else if (type == eNamedSummary) 1425 { 1426 // system named summaries do not exist (yet?) 1427 DataVisualization::NamedSummaryFormats::Add(type_name,entry); 1428 return true; 1429 } 1430 else 1431 { 1432 category->GetSummaryNavigator()->Add(type_name, entry); 1433 return true; 1434 } 1435 } 1436 1437 OptionDefinition 1438 CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = 1439 { 1440 { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 1441 { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade to derived typedefs."}, 1442 { 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."}, 1443 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 1444 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 1445 { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, 1446 { LLDB_OPT_SET_1 , true, "inline-children", 'c', no_argument, NULL, 0, eArgTypeNone, "If true, inline all child values into summary string."}, 1447 { LLDB_OPT_SET_2 , true, "summary-string", 's', required_argument, NULL, 0, eArgTypeSummaryString, "Summary string used to display text and object contents."}, 1448 { LLDB_OPT_SET_3, false, "python-script", 'o', required_argument, NULL, 0, eArgTypePythonScript, "Give a one-liner Python script as part of the command."}, 1449 { 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."}, 1450 { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone, "Input Python code to use for this type manually."}, 1451 { 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."}, 1452 { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', required_argument, NULL, 0, eArgTypeName, "A name for this summary string."}, 1453 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1454 }; 1455 1456 1457 //------------------------------------------------------------------------- 1458 // CommandObjectTypeSummaryDelete 1459 //------------------------------------------------------------------------- 1460 1461 class CommandObjectTypeSummaryDelete : public CommandObject 1462 { 1463 private: 1464 class CommandOptions : public Options 1465 { 1466 public: 1467 1468 CommandOptions (CommandInterpreter &interpreter) : 1469 Options (interpreter) 1470 { 1471 } 1472 1473 virtual 1474 ~CommandOptions (){} 1475 1476 virtual Error 1477 SetOptionValue (uint32_t option_idx, const char *option_arg) 1478 { 1479 Error error; 1480 char short_option = (char) m_getopt_table[option_idx].val; 1481 1482 switch (short_option) 1483 { 1484 case 'a': 1485 m_delete_all = true; 1486 break; 1487 case 'w': 1488 m_category = std::string(option_arg); 1489 break; 1490 default: 1491 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1492 break; 1493 } 1494 1495 return error; 1496 } 1497 1498 void 1499 OptionParsingStarting () 1500 { 1501 m_delete_all = false; 1502 m_category = "default"; 1503 } 1504 1505 const OptionDefinition* 1506 GetDefinitions () 1507 { 1508 return g_option_table; 1509 } 1510 1511 // Options table: Required for subclasses of Options. 1512 1513 static OptionDefinition g_option_table[]; 1514 1515 // Instance variables to hold the values for command options. 1516 1517 bool m_delete_all; 1518 std::string m_category; 1519 1520 }; 1521 1522 CommandOptions m_options; 1523 1524 virtual Options * 1525 GetOptions () 1526 { 1527 return &m_options; 1528 } 1529 1530 static bool 1531 PerCategoryCallback(void* param, 1532 const lldb::FormatCategorySP& cate) 1533 { 1534 ConstString *name = (ConstString*)param; 1535 cate->Delete(*name, eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary); 1536 return true; 1537 } 1538 1539 public: 1540 CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) : 1541 CommandObject (interpreter, 1542 "type summary delete", 1543 "Delete an existing summary style for a type.", 1544 NULL), m_options(interpreter) 1545 { 1546 CommandArgumentEntry type_arg; 1547 CommandArgumentData type_style_arg; 1548 1549 type_style_arg.arg_type = eArgTypeName; 1550 type_style_arg.arg_repetition = eArgRepeatPlain; 1551 1552 type_arg.push_back (type_style_arg); 1553 1554 m_arguments.push_back (type_arg); 1555 1556 } 1557 1558 ~CommandObjectTypeSummaryDelete () 1559 { 1560 } 1561 1562 bool 1563 Execute (Args& command, CommandReturnObject &result) 1564 { 1565 const size_t argc = command.GetArgumentCount(); 1566 1567 if (argc != 1) 1568 { 1569 result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); 1570 result.SetStatus(eReturnStatusFailed); 1571 return false; 1572 } 1573 1574 const char* typeA = command.GetArgumentAtIndex(0); 1575 ConstString typeCS(typeA); 1576 1577 if (!typeCS) 1578 { 1579 result.AppendError("empty typenames not allowed"); 1580 result.SetStatus(eReturnStatusFailed); 1581 return false; 1582 } 1583 1584 if (m_options.m_delete_all) 1585 { 1586 DataVisualization::Categories::LoopThrough(PerCategoryCallback, (void*)typeCS.GetCString()); 1587 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1588 return result.Succeeded(); 1589 } 1590 1591 lldb::FormatCategorySP category; 1592 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 1593 1594 bool delete_category = category->Delete(typeCS, 1595 eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary); 1596 bool delete_named = DataVisualization::NamedSummaryFormats::Delete(typeCS); 1597 1598 if (delete_category || delete_named) 1599 { 1600 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1601 return result.Succeeded(); 1602 } 1603 else 1604 { 1605 result.AppendErrorWithFormat ("no custom summary for %s.\n", typeA); 1606 result.SetStatus(eReturnStatusFailed); 1607 return false; 1608 } 1609 1610 } 1611 }; 1612 1613 OptionDefinition 1614 CommandObjectTypeSummaryDelete::CommandOptions::g_option_table[] = 1615 { 1616 { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Delete from every category."}, 1617 { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Delete from given category."}, 1618 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1619 }; 1620 1621 class CommandObjectTypeSummaryClear : public CommandObject 1622 { 1623 private: 1624 1625 class CommandOptions : public Options 1626 { 1627 public: 1628 1629 CommandOptions (CommandInterpreter &interpreter) : 1630 Options (interpreter) 1631 { 1632 } 1633 1634 virtual 1635 ~CommandOptions (){} 1636 1637 virtual Error 1638 SetOptionValue (uint32_t option_idx, const char *option_arg) 1639 { 1640 Error error; 1641 char short_option = (char) m_getopt_table[option_idx].val; 1642 1643 switch (short_option) 1644 { 1645 case 'a': 1646 m_delete_all = true; 1647 break; 1648 default: 1649 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1650 break; 1651 } 1652 1653 return error; 1654 } 1655 1656 void 1657 OptionParsingStarting () 1658 { 1659 m_delete_all = false; 1660 } 1661 1662 const OptionDefinition* 1663 GetDefinitions () 1664 { 1665 return g_option_table; 1666 } 1667 1668 // Options table: Required for subclasses of Options. 1669 1670 static OptionDefinition g_option_table[]; 1671 1672 // Instance variables to hold the values for command options. 1673 1674 bool m_delete_all; 1675 bool m_delete_named; 1676 }; 1677 1678 CommandOptions m_options; 1679 1680 virtual Options * 1681 GetOptions () 1682 { 1683 return &m_options; 1684 } 1685 1686 static bool 1687 PerCategoryCallback(void* param, 1688 const lldb::FormatCategorySP& cate) 1689 { 1690 cate->GetSummaryNavigator()->Clear(); 1691 cate->GetRegexSummaryNavigator()->Clear(); 1692 return true; 1693 1694 } 1695 1696 public: 1697 CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) : 1698 CommandObject (interpreter, 1699 "type summary clear", 1700 "Delete all existing summary styles.", 1701 NULL), m_options(interpreter) 1702 { 1703 } 1704 1705 ~CommandObjectTypeSummaryClear () 1706 { 1707 } 1708 1709 bool 1710 Execute (Args& command, CommandReturnObject &result) 1711 { 1712 1713 if (m_options.m_delete_all) 1714 DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL); 1715 1716 else 1717 { 1718 lldb::FormatCategorySP category; 1719 if (command.GetArgumentCount() > 0) 1720 { 1721 const char* cat_name = command.GetArgumentAtIndex(0); 1722 ConstString cat_nameCS(cat_name); 1723 DataVisualization::Categories::GetCategory(cat_nameCS, category); 1724 } 1725 else 1726 DataVisualization::Categories::GetCategory(ConstString(NULL), category); 1727 category->Clear(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary); 1728 } 1729 1730 DataVisualization::NamedSummaryFormats::Clear(); 1731 1732 result.SetStatus(eReturnStatusSuccessFinishResult); 1733 return result.Succeeded(); 1734 } 1735 1736 }; 1737 1738 OptionDefinition 1739 CommandObjectTypeSummaryClear::CommandOptions::g_option_table[] = 1740 { 1741 { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Clear every category."}, 1742 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1743 }; 1744 1745 //------------------------------------------------------------------------- 1746 // CommandObjectTypeSummaryList 1747 //------------------------------------------------------------------------- 1748 1749 bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, ConstString type, const StringSummaryFormat::SharedPointer& entry); 1750 bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const StringSummaryFormat::SharedPointer& entry); 1751 1752 class CommandObjectTypeSummaryList; 1753 1754 struct CommandObjectTypeSummaryList_LoopCallbackParam { 1755 CommandObjectTypeSummaryList* self; 1756 CommandReturnObject* result; 1757 RegularExpression* regex; 1758 RegularExpression* cate_regex; 1759 CommandObjectTypeSummaryList_LoopCallbackParam(CommandObjectTypeSummaryList* S, CommandReturnObject* R, 1760 RegularExpression* X = NULL, 1761 RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {} 1762 }; 1763 1764 class CommandObjectTypeSummaryList : public CommandObject 1765 { 1766 1767 class CommandOptions : public Options 1768 { 1769 public: 1770 1771 CommandOptions (CommandInterpreter &interpreter) : 1772 Options (interpreter) 1773 { 1774 } 1775 1776 virtual 1777 ~CommandOptions (){} 1778 1779 virtual Error 1780 SetOptionValue (uint32_t option_idx, const char *option_arg) 1781 { 1782 Error error; 1783 char short_option = (char) m_getopt_table[option_idx].val; 1784 1785 switch (short_option) 1786 { 1787 case 'w': 1788 m_category_regex = std::string(option_arg); 1789 break; 1790 default: 1791 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1792 break; 1793 } 1794 1795 return error; 1796 } 1797 1798 void 1799 OptionParsingStarting () 1800 { 1801 m_category_regex = ""; 1802 } 1803 1804 const OptionDefinition* 1805 GetDefinitions () 1806 { 1807 return g_option_table; 1808 } 1809 1810 // Options table: Required for subclasses of Options. 1811 1812 static OptionDefinition g_option_table[]; 1813 1814 // Instance variables to hold the values for command options. 1815 1816 std::string m_category_regex; 1817 1818 }; 1819 1820 CommandOptions m_options; 1821 1822 virtual Options * 1823 GetOptions () 1824 { 1825 return &m_options; 1826 } 1827 1828 public: 1829 CommandObjectTypeSummaryList (CommandInterpreter &interpreter) : 1830 CommandObject (interpreter, 1831 "type summary list", 1832 "Show a list of current summary styles.", 1833 NULL), m_options(interpreter) 1834 { 1835 CommandArgumentEntry type_arg; 1836 CommandArgumentData type_style_arg; 1837 1838 type_style_arg.arg_type = eArgTypeName; 1839 type_style_arg.arg_repetition = eArgRepeatOptional; 1840 1841 type_arg.push_back (type_style_arg); 1842 1843 m_arguments.push_back (type_arg); 1844 } 1845 1846 ~CommandObjectTypeSummaryList () 1847 { 1848 } 1849 1850 bool 1851 Execute (Args& command, CommandReturnObject &result) 1852 { 1853 const size_t argc = command.GetArgumentCount(); 1854 1855 CommandObjectTypeSummaryList_LoopCallbackParam *param; 1856 RegularExpression* cate_regex = 1857 m_options.m_category_regex.empty() ? NULL : 1858 new RegularExpression(m_options.m_category_regex.c_str()); 1859 1860 if (argc == 1) 1861 { 1862 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 1863 regex->Compile(command.GetArgumentAtIndex(0)); 1864 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex,cate_regex); 1865 } 1866 else 1867 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,NULL,cate_regex); 1868 1869 DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); 1870 1871 if (DataVisualization::NamedSummaryFormats::GetCount() > 0) 1872 { 1873 result.GetOutputStream().Printf("Named summaries:\n"); 1874 if (argc == 1) 1875 { 1876 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 1877 regex->Compile(command.GetArgumentAtIndex(0)); 1878 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex); 1879 } 1880 else 1881 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result); 1882 DataVisualization::NamedSummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param); 1883 delete param; 1884 } 1885 1886 if (cate_regex) 1887 delete cate_regex; 1888 1889 result.SetStatus(eReturnStatusSuccessFinishResult); 1890 return result.Succeeded(); 1891 } 1892 1893 private: 1894 1895 static bool 1896 PerCategoryCallback(void* param_vp, 1897 const lldb::FormatCategorySP& cate) 1898 { 1899 1900 CommandObjectTypeSummaryList_LoopCallbackParam* param = 1901 (CommandObjectTypeSummaryList_LoopCallbackParam*)param_vp; 1902 CommandReturnObject* result = param->result; 1903 1904 const char* cate_name = cate->GetName().c_str(); 1905 1906 // if the category is disabled or empty and there is no regex, just skip it 1907 if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary) == 0) && param->cate_regex == NULL) 1908 return true; 1909 1910 // if we have a regex and this category does not match it, just skip it 1911 if(param->cate_regex != NULL && param->cate_regex->Execute(cate_name) == false) 1912 return true; 1913 1914 result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n", 1915 cate_name, 1916 (cate->IsEnabled() ? "enabled" : "disabled")); 1917 1918 cate->GetSummaryNavigator()->LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param_vp); 1919 1920 if (cate->GetRegexSummaryNavigator()->GetCount() > 0) 1921 { 1922 result->GetOutputStream().Printf("Regex-based summaries (slower):\n"); 1923 cate->GetRegexSummaryNavigator()->LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, param_vp); 1924 } 1925 return true; 1926 } 1927 1928 1929 bool 1930 LoopCallback (const char* type, 1931 const lldb::SummaryFormatSP& entry, 1932 RegularExpression* regex, 1933 CommandReturnObject *result) 1934 { 1935 if (regex == NULL || regex->Execute(type)) 1936 result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); 1937 return true; 1938 } 1939 1940 friend bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, ConstString type, const lldb::SummaryFormatSP& entry); 1941 friend bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const lldb::SummaryFormatSP& entry); 1942 }; 1943 1944 bool 1945 CommandObjectTypeSummaryList_LoopCallback ( 1946 void* pt2self, 1947 ConstString type, 1948 const lldb::SummaryFormatSP& entry) 1949 { 1950 CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self; 1951 return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result); 1952 } 1953 1954 bool 1955 CommandObjectTypeRXSummaryList_LoopCallback ( 1956 void* pt2self, 1957 lldb::RegularExpressionSP regex, 1958 const lldb::SummaryFormatSP& entry) 1959 { 1960 CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self; 1961 return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); 1962 } 1963 1964 OptionDefinition 1965 CommandObjectTypeSummaryList::CommandOptions::g_option_table[] = 1966 { 1967 { LLDB_OPT_SET_ALL, false, "category-regex", 'w', required_argument, NULL, 0, eArgTypeName, "Only show categories matching this filter."}, 1968 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1969 }; 1970 1971 //------------------------------------------------------------------------- 1972 // CommandObjectTypeCategoryEnable 1973 //------------------------------------------------------------------------- 1974 1975 class CommandObjectTypeCategoryEnable : public CommandObject 1976 { 1977 public: 1978 CommandObjectTypeCategoryEnable (CommandInterpreter &interpreter) : 1979 CommandObject (interpreter, 1980 "type category enable", 1981 "Enable a category as a source of formatters.", 1982 NULL) 1983 { 1984 CommandArgumentEntry type_arg; 1985 CommandArgumentData type_style_arg; 1986 1987 type_style_arg.arg_type = eArgTypeName; 1988 type_style_arg.arg_repetition = eArgRepeatPlus; 1989 1990 type_arg.push_back (type_style_arg); 1991 1992 m_arguments.push_back (type_arg); 1993 1994 } 1995 1996 ~CommandObjectTypeCategoryEnable () 1997 { 1998 } 1999 2000 bool 2001 Execute (Args& command, CommandReturnObject &result) 2002 { 2003 const size_t argc = command.GetArgumentCount(); 2004 2005 if (argc < 1) 2006 { 2007 result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str()); 2008 result.SetStatus(eReturnStatusFailed); 2009 return false; 2010 } 2011 2012 for (int i = argc - 1; i >= 0; i--) 2013 { 2014 const char* typeA = command.GetArgumentAtIndex(i); 2015 ConstString typeCS(typeA); 2016 2017 if (!typeCS) 2018 { 2019 result.AppendError("empty category name not allowed"); 2020 result.SetStatus(eReturnStatusFailed); 2021 return false; 2022 } 2023 DataVisualization::Categories::Enable(typeCS); 2024 lldb::FormatCategorySP cate; 2025 if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate.get()) 2026 { 2027 if (cate->GetCount() == 0) 2028 { 2029 result.AppendWarning("empty category enabled (typo?)"); 2030 } 2031 } 2032 } 2033 2034 result.SetStatus(eReturnStatusSuccessFinishResult); 2035 return result.Succeeded(); 2036 } 2037 2038 }; 2039 2040 //------------------------------------------------------------------------- 2041 // CommandObjectTypeCategoryDelete 2042 //------------------------------------------------------------------------- 2043 2044 class CommandObjectTypeCategoryDelete : public CommandObject 2045 { 2046 public: 2047 CommandObjectTypeCategoryDelete (CommandInterpreter &interpreter) : 2048 CommandObject (interpreter, 2049 "type category delete", 2050 "Delete a category and all associated formatters.", 2051 NULL) 2052 { 2053 CommandArgumentEntry type_arg; 2054 CommandArgumentData type_style_arg; 2055 2056 type_style_arg.arg_type = eArgTypeName; 2057 type_style_arg.arg_repetition = eArgRepeatPlus; 2058 2059 type_arg.push_back (type_style_arg); 2060 2061 m_arguments.push_back (type_arg); 2062 2063 } 2064 2065 ~CommandObjectTypeCategoryDelete () 2066 { 2067 } 2068 2069 bool 2070 Execute (Args& command, CommandReturnObject &result) 2071 { 2072 const size_t argc = command.GetArgumentCount(); 2073 2074 if (argc < 1) 2075 { 2076 result.AppendErrorWithFormat ("%s takes 1 or more arg.\n", m_cmd_name.c_str()); 2077 result.SetStatus(eReturnStatusFailed); 2078 return false; 2079 } 2080 2081 bool success = true; 2082 2083 // the order is not relevant here 2084 for (int i = argc - 1; i >= 0; i--) 2085 { 2086 const char* typeA = command.GetArgumentAtIndex(i); 2087 ConstString typeCS(typeA); 2088 2089 if (!typeCS) 2090 { 2091 result.AppendError("empty category name not allowed"); 2092 result.SetStatus(eReturnStatusFailed); 2093 return false; 2094 } 2095 if (!DataVisualization::Categories::Delete(typeCS)) 2096 success = false; // keep deleting even if we hit an error 2097 } 2098 if (success) 2099 { 2100 result.SetStatus(eReturnStatusSuccessFinishResult); 2101 return result.Succeeded(); 2102 } 2103 else 2104 { 2105 result.AppendError("cannot delete one or more categories\n"); 2106 result.SetStatus(eReturnStatusFailed); 2107 return false; 2108 } 2109 } 2110 }; 2111 2112 //------------------------------------------------------------------------- 2113 // CommandObjectTypeCategoryDisable 2114 //------------------------------------------------------------------------- 2115 2116 class CommandObjectTypeCategoryDisable : public CommandObject 2117 { 2118 public: 2119 CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) : 2120 CommandObject (interpreter, 2121 "type category disable", 2122 "Disable a category as a source of formatters.", 2123 NULL) 2124 { 2125 CommandArgumentEntry type_arg; 2126 CommandArgumentData type_style_arg; 2127 2128 type_style_arg.arg_type = eArgTypeName; 2129 type_style_arg.arg_repetition = eArgRepeatPlus; 2130 2131 type_arg.push_back (type_style_arg); 2132 2133 m_arguments.push_back (type_arg); 2134 2135 } 2136 2137 ~CommandObjectTypeCategoryDisable () 2138 { 2139 } 2140 2141 bool 2142 Execute (Args& command, CommandReturnObject &result) 2143 { 2144 const size_t argc = command.GetArgumentCount(); 2145 2146 if (argc < 1) 2147 { 2148 result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str()); 2149 result.SetStatus(eReturnStatusFailed); 2150 return false; 2151 } 2152 2153 // the order is not relevant here 2154 for (int i = argc - 1; i >= 0; i--) 2155 { 2156 const char* typeA = command.GetArgumentAtIndex(i); 2157 ConstString typeCS(typeA); 2158 2159 if (!typeCS) 2160 { 2161 result.AppendError("empty category name not allowed"); 2162 result.SetStatus(eReturnStatusFailed); 2163 return false; 2164 } 2165 DataVisualization::Categories::Disable(typeCS); 2166 } 2167 2168 result.SetStatus(eReturnStatusSuccessFinishResult); 2169 return result.Succeeded(); 2170 } 2171 2172 }; 2173 2174 //------------------------------------------------------------------------- 2175 // CommandObjectTypeCategoryList 2176 //------------------------------------------------------------------------- 2177 2178 class CommandObjectTypeCategoryList : public CommandObject 2179 { 2180 private: 2181 2182 struct CommandObjectTypeCategoryList_CallbackParam 2183 { 2184 CommandReturnObject* result; 2185 RegularExpression* regex; 2186 2187 CommandObjectTypeCategoryList_CallbackParam(CommandReturnObject* res, 2188 RegularExpression* rex = NULL) : 2189 result(res), 2190 regex(rex) 2191 { 2192 } 2193 2194 }; 2195 2196 static bool 2197 PerCategoryCallback(void* param_vp, 2198 const lldb::FormatCategorySP& cate) 2199 { 2200 CommandObjectTypeCategoryList_CallbackParam* param = 2201 (CommandObjectTypeCategoryList_CallbackParam*)param_vp; 2202 CommandReturnObject* result = param->result; 2203 RegularExpression* regex = param->regex; 2204 2205 const char* cate_name = cate->GetName().c_str(); 2206 2207 if (regex == NULL || regex->Execute(cate_name)) 2208 result->GetOutputStream().Printf("Category %s is%s enabled\n", 2209 cate_name, 2210 (cate->IsEnabled() ? "" : " not")); 2211 return true; 2212 } 2213 public: 2214 CommandObjectTypeCategoryList (CommandInterpreter &interpreter) : 2215 CommandObject (interpreter, 2216 "type category list", 2217 "Provide a list of all existing categories.", 2218 NULL) 2219 { 2220 CommandArgumentEntry type_arg; 2221 CommandArgumentData type_style_arg; 2222 2223 type_style_arg.arg_type = eArgTypeName; 2224 type_style_arg.arg_repetition = eArgRepeatOptional; 2225 2226 type_arg.push_back (type_style_arg); 2227 2228 m_arguments.push_back (type_arg); 2229 } 2230 2231 ~CommandObjectTypeCategoryList () 2232 { 2233 } 2234 2235 bool 2236 Execute (Args& command, CommandReturnObject &result) 2237 { 2238 const size_t argc = command.GetArgumentCount(); 2239 RegularExpression* regex = NULL; 2240 2241 if (argc == 0) 2242 ; 2243 else if (argc == 1) 2244 regex = new RegularExpression(command.GetArgumentAtIndex(0)); 2245 else 2246 { 2247 result.AppendErrorWithFormat ("%s takes 0 or one arg.\n", m_cmd_name.c_str()); 2248 result.SetStatus(eReturnStatusFailed); 2249 return false; 2250 } 2251 2252 CommandObjectTypeCategoryList_CallbackParam param(&result, 2253 regex); 2254 2255 DataVisualization::Categories::LoopThrough(PerCategoryCallback, ¶m); 2256 2257 if (regex) 2258 delete regex; 2259 2260 result.SetStatus(eReturnStatusSuccessFinishResult); 2261 return result.Succeeded(); 2262 } 2263 2264 }; 2265 2266 //------------------------------------------------------------------------- 2267 // CommandObjectTypeFilterList 2268 //------------------------------------------------------------------------- 2269 2270 bool CommandObjectTypeFilterList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry); 2271 bool CommandObjectTypeFilterRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry); 2272 2273 class CommandObjectTypeFilterList; 2274 2275 struct CommandObjectTypeFilterList_LoopCallbackParam { 2276 CommandObjectTypeFilterList* self; 2277 CommandReturnObject* result; 2278 RegularExpression* regex; 2279 RegularExpression* cate_regex; 2280 CommandObjectTypeFilterList_LoopCallbackParam(CommandObjectTypeFilterList* S, CommandReturnObject* R, 2281 RegularExpression* X = NULL, 2282 RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {} 2283 }; 2284 2285 class CommandObjectTypeFilterList : public CommandObject 2286 { 2287 2288 class CommandOptions : public Options 2289 { 2290 public: 2291 2292 CommandOptions (CommandInterpreter &interpreter) : 2293 Options (interpreter) 2294 { 2295 } 2296 2297 virtual 2298 ~CommandOptions (){} 2299 2300 virtual Error 2301 SetOptionValue (uint32_t option_idx, const char *option_arg) 2302 { 2303 Error error; 2304 char short_option = (char) m_getopt_table[option_idx].val; 2305 2306 switch (short_option) 2307 { 2308 case 'w': 2309 m_category_regex = std::string(option_arg); 2310 break; 2311 default: 2312 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2313 break; 2314 } 2315 2316 return error; 2317 } 2318 2319 void 2320 OptionParsingStarting () 2321 { 2322 m_category_regex = ""; 2323 } 2324 2325 const OptionDefinition* 2326 GetDefinitions () 2327 { 2328 return g_option_table; 2329 } 2330 2331 // Options table: Required for subclasses of Options. 2332 2333 static OptionDefinition g_option_table[]; 2334 2335 // Instance variables to hold the values for command options. 2336 2337 std::string m_category_regex; 2338 2339 }; 2340 2341 CommandOptions m_options; 2342 2343 virtual Options * 2344 GetOptions () 2345 { 2346 return &m_options; 2347 } 2348 2349 public: 2350 CommandObjectTypeFilterList (CommandInterpreter &interpreter) : 2351 CommandObject (interpreter, 2352 "type filter list", 2353 "Show a list of current filters.", 2354 NULL), m_options(interpreter) 2355 { 2356 CommandArgumentEntry type_arg; 2357 CommandArgumentData type_style_arg; 2358 2359 type_style_arg.arg_type = eArgTypeName; 2360 type_style_arg.arg_repetition = eArgRepeatOptional; 2361 2362 type_arg.push_back (type_style_arg); 2363 2364 m_arguments.push_back (type_arg); 2365 } 2366 2367 ~CommandObjectTypeFilterList () 2368 { 2369 } 2370 2371 bool 2372 Execute (Args& command, CommandReturnObject &result) 2373 { 2374 const size_t argc = command.GetArgumentCount(); 2375 2376 CommandObjectTypeFilterList_LoopCallbackParam *param; 2377 RegularExpression* cate_regex = 2378 m_options.m_category_regex.empty() ? NULL : 2379 new RegularExpression(m_options.m_category_regex.c_str()); 2380 2381 if (argc == 1) 2382 { 2383 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 2384 regex->Compile(command.GetArgumentAtIndex(0)); 2385 param = new CommandObjectTypeFilterList_LoopCallbackParam(this,&result,regex,cate_regex); 2386 } 2387 else 2388 param = new CommandObjectTypeFilterList_LoopCallbackParam(this,&result,NULL,cate_regex); 2389 2390 DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); 2391 2392 if (cate_regex) 2393 delete cate_regex; 2394 2395 result.SetStatus(eReturnStatusSuccessFinishResult); 2396 return result.Succeeded(); 2397 } 2398 2399 private: 2400 2401 static bool 2402 PerCategoryCallback(void* param_vp, 2403 const lldb::FormatCategorySP& cate) 2404 { 2405 2406 const char* cate_name = cate->GetName().c_str(); 2407 2408 CommandObjectTypeFilterList_LoopCallbackParam* param = 2409 (CommandObjectTypeFilterList_LoopCallbackParam*)param_vp; 2410 CommandReturnObject* result = param->result; 2411 2412 // if the category is disabled or empty and there is no regex, just skip it 2413 if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter) == 0) && param->cate_regex == NULL) 2414 return true; 2415 2416 // if we have a regex and this category does not match it, just skip it 2417 if(param->cate_regex != NULL && param->cate_regex->Execute(cate_name) == false) 2418 return true; 2419 2420 result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n", 2421 cate_name, 2422 (cate->IsEnabled() ? "enabled" : "disabled")); 2423 2424 cate->GetFilterNavigator()->LoopThrough(CommandObjectTypeFilterList_LoopCallback, param_vp); 2425 2426 if (cate->GetRegexFilterNavigator()->GetCount() > 0) 2427 { 2428 result->GetOutputStream().Printf("Regex-based filters (slower):\n"); 2429 cate->GetRegexFilterNavigator()->LoopThrough(CommandObjectTypeFilterRXList_LoopCallback, param_vp); 2430 } 2431 2432 return true; 2433 } 2434 2435 bool 2436 LoopCallback (const char* type, 2437 const SyntheticChildren::SharedPointer& entry, 2438 RegularExpression* regex, 2439 CommandReturnObject *result) 2440 { 2441 if (regex == NULL || regex->Execute(type)) 2442 result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); 2443 return true; 2444 } 2445 2446 friend bool CommandObjectTypeFilterList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry); 2447 friend bool CommandObjectTypeFilterRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry); 2448 }; 2449 2450 bool 2451 CommandObjectTypeFilterList_LoopCallback (void* pt2self, 2452 ConstString type, 2453 const SyntheticChildren::SharedPointer& entry) 2454 { 2455 CommandObjectTypeFilterList_LoopCallbackParam* param = (CommandObjectTypeFilterList_LoopCallbackParam*)pt2self; 2456 return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result); 2457 } 2458 2459 bool 2460 CommandObjectTypeFilterRXList_LoopCallback (void* pt2self, 2461 lldb::RegularExpressionSP regex, 2462 const SyntheticChildren::SharedPointer& entry) 2463 { 2464 CommandObjectTypeFilterList_LoopCallbackParam* param = (CommandObjectTypeFilterList_LoopCallbackParam*)pt2self; 2465 return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); 2466 } 2467 2468 2469 OptionDefinition 2470 CommandObjectTypeFilterList::CommandOptions::g_option_table[] = 2471 { 2472 { LLDB_OPT_SET_ALL, false, "category-regex", 'w', required_argument, NULL, 0, eArgTypeName, "Only show categories matching this filter."}, 2473 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 2474 }; 2475 2476 #ifndef LLDB_DISABLE_PYTHON 2477 2478 //------------------------------------------------------------------------- 2479 // CommandObjectTypeSynthList 2480 //------------------------------------------------------------------------- 2481 2482 bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry); 2483 bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry); 2484 2485 class CommandObjectTypeSynthList; 2486 2487 struct CommandObjectTypeSynthList_LoopCallbackParam { 2488 CommandObjectTypeSynthList* self; 2489 CommandReturnObject* result; 2490 RegularExpression* regex; 2491 RegularExpression* cate_regex; 2492 CommandObjectTypeSynthList_LoopCallbackParam(CommandObjectTypeSynthList* S, CommandReturnObject* R, 2493 RegularExpression* X = NULL, 2494 RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {} 2495 }; 2496 2497 class CommandObjectTypeSynthList : public CommandObject 2498 { 2499 2500 class CommandOptions : public Options 2501 { 2502 public: 2503 2504 CommandOptions (CommandInterpreter &interpreter) : 2505 Options (interpreter) 2506 { 2507 } 2508 2509 virtual 2510 ~CommandOptions (){} 2511 2512 virtual Error 2513 SetOptionValue (uint32_t option_idx, const char *option_arg) 2514 { 2515 Error error; 2516 char short_option = (char) m_getopt_table[option_idx].val; 2517 2518 switch (short_option) 2519 { 2520 case 'w': 2521 m_category_regex = std::string(option_arg); 2522 break; 2523 default: 2524 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2525 break; 2526 } 2527 2528 return error; 2529 } 2530 2531 void 2532 OptionParsingStarting () 2533 { 2534 m_category_regex = ""; 2535 } 2536 2537 const OptionDefinition* 2538 GetDefinitions () 2539 { 2540 return g_option_table; 2541 } 2542 2543 // Options table: Required for subclasses of Options. 2544 2545 static OptionDefinition g_option_table[]; 2546 2547 // Instance variables to hold the values for command options. 2548 2549 std::string m_category_regex; 2550 2551 }; 2552 2553 CommandOptions m_options; 2554 2555 virtual Options * 2556 GetOptions () 2557 { 2558 return &m_options; 2559 } 2560 2561 public: 2562 CommandObjectTypeSynthList (CommandInterpreter &interpreter) : 2563 CommandObject (interpreter, 2564 "type synthetic list", 2565 "Show a list of current synthetic providers.", 2566 NULL), m_options(interpreter) 2567 { 2568 CommandArgumentEntry type_arg; 2569 CommandArgumentData type_style_arg; 2570 2571 type_style_arg.arg_type = eArgTypeName; 2572 type_style_arg.arg_repetition = eArgRepeatOptional; 2573 2574 type_arg.push_back (type_style_arg); 2575 2576 m_arguments.push_back (type_arg); 2577 } 2578 2579 ~CommandObjectTypeSynthList () 2580 { 2581 } 2582 2583 bool 2584 Execute (Args& command, CommandReturnObject &result) 2585 { 2586 const size_t argc = command.GetArgumentCount(); 2587 2588 CommandObjectTypeSynthList_LoopCallbackParam *param; 2589 RegularExpression* cate_regex = 2590 m_options.m_category_regex.empty() ? NULL : 2591 new RegularExpression(m_options.m_category_regex.c_str()); 2592 2593 if (argc == 1) 2594 { 2595 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 2596 regex->Compile(command.GetArgumentAtIndex(0)); 2597 param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,regex,cate_regex); 2598 } 2599 else 2600 param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,NULL,cate_regex); 2601 2602 DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); 2603 2604 if (cate_regex) 2605 delete cate_regex; 2606 2607 result.SetStatus(eReturnStatusSuccessFinishResult); 2608 return result.Succeeded(); 2609 } 2610 2611 private: 2612 2613 static bool 2614 PerCategoryCallback(void* param_vp, 2615 const lldb::FormatCategorySP& cate) 2616 { 2617 2618 CommandObjectTypeSynthList_LoopCallbackParam* param = 2619 (CommandObjectTypeSynthList_LoopCallbackParam*)param_vp; 2620 CommandReturnObject* result = param->result; 2621 2622 const char* cate_name = cate->GetName().c_str(); 2623 2624 // if the category is disabled or empty and there is no regex, just skip it 2625 if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth) == 0) && param->cate_regex == NULL) 2626 return true; 2627 2628 // if we have a regex and this category does not match it, just skip it 2629 if(param->cate_regex != NULL && param->cate_regex->Execute(cate_name) == false) 2630 return true; 2631 2632 result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n", 2633 cate_name, 2634 (cate->IsEnabled() ? "enabled" : "disabled")); 2635 2636 cate->GetSyntheticNavigator()->LoopThrough(CommandObjectTypeSynthList_LoopCallback, param_vp); 2637 2638 if (cate->GetRegexSyntheticNavigator()->GetCount() > 0) 2639 { 2640 result->GetOutputStream().Printf("Regex-based synthetic providers (slower):\n"); 2641 cate->GetRegexSyntheticNavigator()->LoopThrough(CommandObjectTypeSynthRXList_LoopCallback, param_vp); 2642 } 2643 2644 return true; 2645 } 2646 2647 bool 2648 LoopCallback (const char* type, 2649 const SyntheticChildren::SharedPointer& entry, 2650 RegularExpression* regex, 2651 CommandReturnObject *result) 2652 { 2653 if (regex == NULL || regex->Execute(type)) 2654 result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); 2655 return true; 2656 } 2657 2658 friend bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry); 2659 friend bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry); 2660 }; 2661 2662 bool 2663 CommandObjectTypeSynthList_LoopCallback (void* pt2self, 2664 ConstString type, 2665 const SyntheticChildren::SharedPointer& entry) 2666 { 2667 CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self; 2668 return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result); 2669 } 2670 2671 bool 2672 CommandObjectTypeSynthRXList_LoopCallback (void* pt2self, 2673 lldb::RegularExpressionSP regex, 2674 const SyntheticChildren::SharedPointer& entry) 2675 { 2676 CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self; 2677 return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); 2678 } 2679 2680 2681 OptionDefinition 2682 CommandObjectTypeSynthList::CommandOptions::g_option_table[] = 2683 { 2684 { LLDB_OPT_SET_ALL, false, "category-regex", 'w', required_argument, NULL, 0, eArgTypeName, "Only show categories matching this filter."}, 2685 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 2686 }; 2687 2688 #endif // #ifndef LLDB_DISABLE_PYTHON 2689 //------------------------------------------------------------------------- 2690 // CommandObjectTypeFilterDelete 2691 //------------------------------------------------------------------------- 2692 2693 class CommandObjectTypeFilterDelete : public CommandObject 2694 { 2695 private: 2696 class CommandOptions : public Options 2697 { 2698 public: 2699 2700 CommandOptions (CommandInterpreter &interpreter) : 2701 Options (interpreter) 2702 { 2703 } 2704 2705 virtual 2706 ~CommandOptions (){} 2707 2708 virtual Error 2709 SetOptionValue (uint32_t option_idx, const char *option_arg) 2710 { 2711 Error error; 2712 char short_option = (char) m_getopt_table[option_idx].val; 2713 2714 switch (short_option) 2715 { 2716 case 'a': 2717 m_delete_all = true; 2718 break; 2719 case 'w': 2720 m_category = std::string(option_arg); 2721 break; 2722 default: 2723 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2724 break; 2725 } 2726 2727 return error; 2728 } 2729 2730 void 2731 OptionParsingStarting () 2732 { 2733 m_delete_all = false; 2734 m_category = "default"; 2735 } 2736 2737 const OptionDefinition* 2738 GetDefinitions () 2739 { 2740 return g_option_table; 2741 } 2742 2743 // Options table: Required for subclasses of Options. 2744 2745 static OptionDefinition g_option_table[]; 2746 2747 // Instance variables to hold the values for command options. 2748 2749 bool m_delete_all; 2750 std::string m_category; 2751 2752 }; 2753 2754 CommandOptions m_options; 2755 2756 virtual Options * 2757 GetOptions () 2758 { 2759 return &m_options; 2760 } 2761 2762 static bool 2763 PerCategoryCallback(void* param, 2764 const lldb::FormatCategorySP& cate) 2765 { 2766 ConstString *name = (ConstString*)param; 2767 return cate->Delete(*name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter); 2768 } 2769 2770 public: 2771 CommandObjectTypeFilterDelete (CommandInterpreter &interpreter) : 2772 CommandObject (interpreter, 2773 "type filter delete", 2774 "Delete an existing filter for a type.", 2775 NULL), m_options(interpreter) 2776 { 2777 CommandArgumentEntry type_arg; 2778 CommandArgumentData type_style_arg; 2779 2780 type_style_arg.arg_type = eArgTypeName; 2781 type_style_arg.arg_repetition = eArgRepeatPlain; 2782 2783 type_arg.push_back (type_style_arg); 2784 2785 m_arguments.push_back (type_arg); 2786 2787 } 2788 2789 ~CommandObjectTypeFilterDelete () 2790 { 2791 } 2792 2793 bool 2794 Execute (Args& command, CommandReturnObject &result) 2795 { 2796 const size_t argc = command.GetArgumentCount(); 2797 2798 if (argc != 1) 2799 { 2800 result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); 2801 result.SetStatus(eReturnStatusFailed); 2802 return false; 2803 } 2804 2805 const char* typeA = command.GetArgumentAtIndex(0); 2806 ConstString typeCS(typeA); 2807 2808 if (!typeCS) 2809 { 2810 result.AppendError("empty typenames not allowed"); 2811 result.SetStatus(eReturnStatusFailed); 2812 return false; 2813 } 2814 2815 if (m_options.m_delete_all) 2816 { 2817 DataVisualization::Categories::LoopThrough(PerCategoryCallback, (void*)&typeCS); 2818 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2819 return result.Succeeded(); 2820 } 2821 2822 lldb::FormatCategorySP category; 2823 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 2824 2825 bool delete_category = category->GetFilterNavigator()->Delete(typeCS); 2826 delete_category = category->GetRegexFilterNavigator()->Delete(typeCS) || delete_category; 2827 2828 if (delete_category) 2829 { 2830 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2831 return result.Succeeded(); 2832 } 2833 else 2834 { 2835 result.AppendErrorWithFormat ("no custom synthetic provider for %s.\n", typeA); 2836 result.SetStatus(eReturnStatusFailed); 2837 return false; 2838 } 2839 2840 } 2841 }; 2842 2843 OptionDefinition 2844 CommandObjectTypeFilterDelete::CommandOptions::g_option_table[] = 2845 { 2846 { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Delete from every category."}, 2847 { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Delete from given category."}, 2848 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 2849 }; 2850 2851 #ifndef LLDB_DISABLE_PYTHON 2852 2853 //------------------------------------------------------------------------- 2854 // CommandObjectTypeSynthDelete 2855 //------------------------------------------------------------------------- 2856 2857 class CommandObjectTypeSynthDelete : public CommandObject 2858 { 2859 private: 2860 class CommandOptions : public Options 2861 { 2862 public: 2863 2864 CommandOptions (CommandInterpreter &interpreter) : 2865 Options (interpreter) 2866 { 2867 } 2868 2869 virtual 2870 ~CommandOptions (){} 2871 2872 virtual Error 2873 SetOptionValue (uint32_t option_idx, const char *option_arg) 2874 { 2875 Error error; 2876 char short_option = (char) m_getopt_table[option_idx].val; 2877 2878 switch (short_option) 2879 { 2880 case 'a': 2881 m_delete_all = true; 2882 break; 2883 case 'w': 2884 m_category = std::string(option_arg); 2885 break; 2886 default: 2887 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 2888 break; 2889 } 2890 2891 return error; 2892 } 2893 2894 void 2895 OptionParsingStarting () 2896 { 2897 m_delete_all = false; 2898 m_category = "default"; 2899 } 2900 2901 const OptionDefinition* 2902 GetDefinitions () 2903 { 2904 return g_option_table; 2905 } 2906 2907 // Options table: Required for subclasses of Options. 2908 2909 static OptionDefinition g_option_table[]; 2910 2911 // Instance variables to hold the values for command options. 2912 2913 bool m_delete_all; 2914 std::string m_category; 2915 2916 }; 2917 2918 CommandOptions m_options; 2919 2920 virtual Options * 2921 GetOptions () 2922 { 2923 return &m_options; 2924 } 2925 2926 static bool 2927 PerCategoryCallback(void* param, 2928 const lldb::FormatCategorySP& cate) 2929 { 2930 ConstString* name = (ConstString*)param; 2931 return cate->Delete(*name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth); 2932 } 2933 2934 public: 2935 CommandObjectTypeSynthDelete (CommandInterpreter &interpreter) : 2936 CommandObject (interpreter, 2937 "type synthetic delete", 2938 "Delete an existing synthetic provider for a type.", 2939 NULL), m_options(interpreter) 2940 { 2941 CommandArgumentEntry type_arg; 2942 CommandArgumentData type_style_arg; 2943 2944 type_style_arg.arg_type = eArgTypeName; 2945 type_style_arg.arg_repetition = eArgRepeatPlain; 2946 2947 type_arg.push_back (type_style_arg); 2948 2949 m_arguments.push_back (type_arg); 2950 2951 } 2952 2953 ~CommandObjectTypeSynthDelete () 2954 { 2955 } 2956 2957 bool 2958 Execute (Args& command, CommandReturnObject &result) 2959 { 2960 const size_t argc = command.GetArgumentCount(); 2961 2962 if (argc != 1) 2963 { 2964 result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); 2965 result.SetStatus(eReturnStatusFailed); 2966 return false; 2967 } 2968 2969 const char* typeA = command.GetArgumentAtIndex(0); 2970 ConstString typeCS(typeA); 2971 2972 if (!typeCS) 2973 { 2974 result.AppendError("empty typenames not allowed"); 2975 result.SetStatus(eReturnStatusFailed); 2976 return false; 2977 } 2978 2979 if (m_options.m_delete_all) 2980 { 2981 DataVisualization::Categories::LoopThrough(PerCategoryCallback, (void*)&typeCS); 2982 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2983 return result.Succeeded(); 2984 } 2985 2986 lldb::FormatCategorySP category; 2987 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 2988 2989 bool delete_category = category->GetSyntheticNavigator()->Delete(typeCS); 2990 delete_category = category->GetRegexSyntheticNavigator()->Delete(typeCS) || delete_category; 2991 2992 if (delete_category) 2993 { 2994 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2995 return result.Succeeded(); 2996 } 2997 else 2998 { 2999 result.AppendErrorWithFormat ("no custom synthetic provider for %s.\n", typeA); 3000 result.SetStatus(eReturnStatusFailed); 3001 return false; 3002 } 3003 3004 } 3005 }; 3006 3007 OptionDefinition 3008 CommandObjectTypeSynthDelete::CommandOptions::g_option_table[] = 3009 { 3010 { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Delete from every category."}, 3011 { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Delete from given category."}, 3012 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 3013 }; 3014 3015 #endif // #ifndef LLDB_DISABLE_PYTHON 3016 3017 //------------------------------------------------------------------------- 3018 // CommandObjectTypeFilterClear 3019 //------------------------------------------------------------------------- 3020 3021 class CommandObjectTypeFilterClear : public CommandObject 3022 { 3023 private: 3024 3025 class CommandOptions : public Options 3026 { 3027 public: 3028 3029 CommandOptions (CommandInterpreter &interpreter) : 3030 Options (interpreter) 3031 { 3032 } 3033 3034 virtual 3035 ~CommandOptions (){} 3036 3037 virtual Error 3038 SetOptionValue (uint32_t option_idx, const char *option_arg) 3039 { 3040 Error error; 3041 char short_option = (char) m_getopt_table[option_idx].val; 3042 3043 switch (short_option) 3044 { 3045 case 'a': 3046 m_delete_all = true; 3047 break; 3048 default: 3049 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 3050 break; 3051 } 3052 3053 return error; 3054 } 3055 3056 void 3057 OptionParsingStarting () 3058 { 3059 m_delete_all = false; 3060 } 3061 3062 const OptionDefinition* 3063 GetDefinitions () 3064 { 3065 return g_option_table; 3066 } 3067 3068 // Options table: Required for subclasses of Options. 3069 3070 static OptionDefinition g_option_table[]; 3071 3072 // Instance variables to hold the values for command options. 3073 3074 bool m_delete_all; 3075 bool m_delete_named; 3076 }; 3077 3078 CommandOptions m_options; 3079 3080 virtual Options * 3081 GetOptions () 3082 { 3083 return &m_options; 3084 } 3085 3086 static bool 3087 PerCategoryCallback(void* param, 3088 const lldb::FormatCategorySP& cate) 3089 { 3090 cate->Clear(eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter); 3091 return true; 3092 3093 } 3094 3095 public: 3096 CommandObjectTypeFilterClear (CommandInterpreter &interpreter) : 3097 CommandObject (interpreter, 3098 "type filter clear", 3099 "Delete all existing filters.", 3100 NULL), m_options(interpreter) 3101 { 3102 } 3103 3104 ~CommandObjectTypeFilterClear () 3105 { 3106 } 3107 3108 bool 3109 Execute (Args& command, CommandReturnObject &result) 3110 { 3111 3112 if (m_options.m_delete_all) 3113 DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL); 3114 3115 else 3116 { 3117 lldb::FormatCategorySP category; 3118 if (command.GetArgumentCount() > 0) 3119 { 3120 const char* cat_name = command.GetArgumentAtIndex(0); 3121 ConstString cat_nameCS(cat_name); 3122 DataVisualization::Categories::GetCategory(cat_nameCS, category); 3123 } 3124 else 3125 DataVisualization::Categories::GetCategory(ConstString(NULL), category); 3126 category->GetFilterNavigator()->Clear(); 3127 category->GetRegexFilterNavigator()->Clear(); 3128 } 3129 3130 result.SetStatus(eReturnStatusSuccessFinishResult); 3131 return result.Succeeded(); 3132 } 3133 3134 }; 3135 3136 OptionDefinition 3137 CommandObjectTypeFilterClear::CommandOptions::g_option_table[] = 3138 { 3139 { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Clear every category."}, 3140 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 3141 }; 3142 3143 #ifndef LLDB_DISABLE_PYTHON 3144 //------------------------------------------------------------------------- 3145 // CommandObjectTypeSynthClear 3146 //------------------------------------------------------------------------- 3147 3148 class CommandObjectTypeSynthClear : public CommandObject 3149 { 3150 private: 3151 3152 class CommandOptions : public Options 3153 { 3154 public: 3155 3156 CommandOptions (CommandInterpreter &interpreter) : 3157 Options (interpreter) 3158 { 3159 } 3160 3161 virtual 3162 ~CommandOptions (){} 3163 3164 virtual Error 3165 SetOptionValue (uint32_t option_idx, const char *option_arg) 3166 { 3167 Error error; 3168 char short_option = (char) m_getopt_table[option_idx].val; 3169 3170 switch (short_option) 3171 { 3172 case 'a': 3173 m_delete_all = true; 3174 break; 3175 default: 3176 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 3177 break; 3178 } 3179 3180 return error; 3181 } 3182 3183 void 3184 OptionParsingStarting () 3185 { 3186 m_delete_all = false; 3187 } 3188 3189 const OptionDefinition* 3190 GetDefinitions () 3191 { 3192 return g_option_table; 3193 } 3194 3195 // Options table: Required for subclasses of Options. 3196 3197 static OptionDefinition g_option_table[]; 3198 3199 // Instance variables to hold the values for command options. 3200 3201 bool m_delete_all; 3202 bool m_delete_named; 3203 }; 3204 3205 CommandOptions m_options; 3206 3207 virtual Options * 3208 GetOptions () 3209 { 3210 return &m_options; 3211 } 3212 3213 static bool 3214 PerCategoryCallback(void* param, 3215 const lldb::FormatCategorySP& cate) 3216 { 3217 cate->Clear(eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth); 3218 return true; 3219 3220 } 3221 3222 public: 3223 CommandObjectTypeSynthClear (CommandInterpreter &interpreter) : 3224 CommandObject (interpreter, 3225 "type synthetic clear", 3226 "Delete all existing synthetic providers.", 3227 NULL), m_options(interpreter) 3228 { 3229 } 3230 3231 ~CommandObjectTypeSynthClear () 3232 { 3233 } 3234 3235 bool 3236 Execute (Args& command, CommandReturnObject &result) 3237 { 3238 3239 if (m_options.m_delete_all) 3240 DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL); 3241 3242 else 3243 { 3244 lldb::FormatCategorySP category; 3245 if (command.GetArgumentCount() > 0) 3246 { 3247 const char* cat_name = command.GetArgumentAtIndex(0); 3248 ConstString cat_nameCS(cat_name); 3249 DataVisualization::Categories::GetCategory(cat_nameCS, category); 3250 } 3251 else 3252 DataVisualization::Categories::GetCategory(ConstString(NULL), category); 3253 category->GetSyntheticNavigator()->Clear(); 3254 category->GetRegexSyntheticNavigator()->Clear(); 3255 } 3256 3257 result.SetStatus(eReturnStatusSuccessFinishResult); 3258 return result.Succeeded(); 3259 } 3260 3261 }; 3262 3263 OptionDefinition 3264 CommandObjectTypeSynthClear::CommandOptions::g_option_table[] = 3265 { 3266 { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Clear every category."}, 3267 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 3268 }; 3269 3270 3271 //------------------------------------------------------------------------- 3272 // TypeSynthAddInputReader 3273 //------------------------------------------------------------------------- 3274 3275 static const char *g_synth_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" 3276 "You must define a Python class with these methods:\n" 3277 " def __init__(self, valobj, dict):\n" 3278 " def num_children(self):\n" 3279 " def get_child_at_index(self, index):\n" 3280 " def get_child_index(self, name):\n" 3281 "Optionally, you can also define a method:\n" 3282 " def update(self):\n" 3283 "if your synthetic provider is holding on to any per-object state variables (currently, this is not implemented because of the way LLDB handles instances of SBValue and you should not rely on object persistence and per-object state)\n" 3284 "class synthProvider:"; 3285 3286 class TypeSynthAddInputReader : public InputReaderEZ 3287 { 3288 public: 3289 TypeSynthAddInputReader(Debugger& debugger) : 3290 InputReaderEZ(debugger) 3291 {} 3292 3293 virtual 3294 ~TypeSynthAddInputReader() 3295 { 3296 } 3297 3298 virtual void ActivateHandler(HandlerData& data) 3299 { 3300 StreamSP out_stream = data.GetOutStream(); 3301 bool batch_mode = data.GetBatchMode(); 3302 if (!batch_mode) 3303 { 3304 out_stream->Printf ("%s\n", g_synth_addreader_instructions); 3305 if (data.reader.GetPrompt()) 3306 out_stream->Printf ("%s", data.reader.GetPrompt()); 3307 out_stream->Flush(); 3308 } 3309 } 3310 3311 virtual void ReactivateHandler(HandlerData& data) 3312 { 3313 StreamSP out_stream = data.GetOutStream(); 3314 bool batch_mode = data.GetBatchMode(); 3315 if (data.reader.GetPrompt() && !batch_mode) 3316 { 3317 out_stream->Printf ("%s", data.reader.GetPrompt()); 3318 out_stream->Flush(); 3319 } 3320 } 3321 virtual void GotTokenHandler(HandlerData& data) 3322 { 3323 StreamSP out_stream = data.GetOutStream(); 3324 bool batch_mode = data.GetBatchMode(); 3325 if (data.bytes && data.bytes_len && data.baton) 3326 { 3327 ((SynthAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len); 3328 } 3329 if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode) 3330 { 3331 out_stream->Printf ("%s", data.reader.GetPrompt()); 3332 out_stream->Flush(); 3333 } 3334 } 3335 virtual void InterruptHandler(HandlerData& data) 3336 { 3337 StreamSP out_stream = data.GetOutStream(); 3338 bool batch_mode = data.GetBatchMode(); 3339 data.reader.SetIsDone (true); 3340 if (!batch_mode) 3341 { 3342 out_stream->Printf ("Warning: No command attached to breakpoint.\n"); 3343 out_stream->Flush(); 3344 } 3345 } 3346 virtual void EOFHandler(HandlerData& data) 3347 { 3348 data.reader.SetIsDone (true); 3349 } 3350 virtual void DoneHandler(HandlerData& data) 3351 { 3352 StreamSP out_stream = data.GetOutStream(); 3353 SynthAddOptions *options_ptr = ((SynthAddOptions*)data.baton); 3354 if (!options_ptr) 3355 { 3356 out_stream->Printf ("Internal error #1: no script attached.\n"); 3357 out_stream->Flush(); 3358 return; 3359 } 3360 3361 SynthAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope 3362 3363 ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 3364 if (!interpreter) 3365 { 3366 out_stream->Printf ("Internal error #2: no script attached.\n"); 3367 out_stream->Flush(); 3368 return; 3369 } 3370 StringList class_name_sl; 3371 if (!interpreter->GenerateTypeSynthClass (options->m_user_source, 3372 class_name_sl)) 3373 { 3374 out_stream->Printf ("Internal error #3: no script attached.\n"); 3375 out_stream->Flush(); 3376 return; 3377 } 3378 if (class_name_sl.GetSize() == 0) 3379 { 3380 out_stream->Printf ("Internal error #4: no script attached.\n"); 3381 out_stream->Flush(); 3382 return; 3383 } 3384 const char *class_name = class_name_sl.GetStringAtIndex(0); 3385 if (!class_name || !class_name[0]) 3386 { 3387 out_stream->Printf ("Internal error #5: no script attached.\n"); 3388 out_stream->Flush(); 3389 return; 3390 } 3391 3392 // everything should be fine now, let's add the synth provider class 3393 3394 SyntheticChildrenSP synth_provider; 3395 synth_provider.reset(new SyntheticScriptProvider(options->m_cascade, 3396 options->m_skip_pointers, 3397 options->m_skip_references, 3398 std::string(class_name))); 3399 3400 3401 lldb::FormatCategorySP category; 3402 DataVisualization::Categories::GetCategory(ConstString(options->m_category.c_str()), category); 3403 3404 Error error; 3405 3406 for (size_t i = 0; i < options->m_target_types.GetSize(); i++) 3407 { 3408 const char *type_name = options->m_target_types.GetStringAtIndex(i); 3409 ConstString typeCS(type_name); 3410 if (typeCS) 3411 { 3412 if (!CommandObjectTypeSynthAdd::AddSynth(typeCS, 3413 synth_provider, 3414 options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth, 3415 options->m_category, 3416 &error)) 3417 { 3418 out_stream->Printf("%s\n", error.AsCString()); 3419 out_stream->Flush(); 3420 return; 3421 } 3422 } 3423 else 3424 { 3425 out_stream->Printf ("Internal error #6: no script attached.\n"); 3426 out_stream->Flush(); 3427 return; 3428 } 3429 } 3430 } 3431 3432 private: 3433 DISALLOW_COPY_AND_ASSIGN (TypeSynthAddInputReader); 3434 }; 3435 3436 void 3437 CommandObjectTypeSynthAdd::CollectPythonScript (SynthAddOptions *options, 3438 CommandReturnObject &result) 3439 { 3440 InputReaderSP reader_sp (new TypeSynthAddInputReader(m_interpreter.GetDebugger())); 3441 if (reader_sp && options) 3442 { 3443 3444 InputReaderEZ::InitializationParameters ipr; 3445 3446 Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt(" "))); 3447 if (err.Success()) 3448 { 3449 m_interpreter.GetDebugger().PushInputReader (reader_sp); 3450 result.SetStatus (eReturnStatusSuccessFinishNoResult); 3451 } 3452 else 3453 { 3454 result.AppendError (err.AsCString()); 3455 result.SetStatus (eReturnStatusFailed); 3456 } 3457 } 3458 else 3459 { 3460 result.AppendError("out of memory"); 3461 result.SetStatus (eReturnStatusFailed); 3462 } 3463 } 3464 3465 bool 3466 CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result) 3467 { 3468 SynthAddOptions *options = new SynthAddOptions ( m_options.m_skip_pointers, 3469 m_options.m_skip_references, 3470 m_options.m_cascade, 3471 m_options.m_regex, 3472 m_options.m_category); 3473 3474 const size_t argc = command.GetArgumentCount(); 3475 3476 for (size_t i = 0; i < argc; i++) 3477 { 3478 const char* typeA = command.GetArgumentAtIndex(i); 3479 if (typeA && *typeA) 3480 options->m_target_types << typeA; 3481 else 3482 { 3483 result.AppendError("empty typenames not allowed"); 3484 result.SetStatus(eReturnStatusFailed); 3485 return false; 3486 } 3487 } 3488 3489 CollectPythonScript(options,result); 3490 return result.Succeeded(); 3491 } 3492 3493 bool 3494 CommandObjectTypeSynthAdd::Execute_PythonClass (Args& command, CommandReturnObject &result) 3495 { 3496 const size_t argc = command.GetArgumentCount(); 3497 3498 if (argc < 1) 3499 { 3500 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 3501 result.SetStatus(eReturnStatusFailed); 3502 return false; 3503 } 3504 3505 if (m_options.m_class_name.empty() && !m_options.m_input_python) 3506 { 3507 result.AppendErrorWithFormat ("%s needs either a Python class name or -P to directly input Python code.\n", m_cmd_name.c_str()); 3508 result.SetStatus(eReturnStatusFailed); 3509 return false; 3510 } 3511 3512 SyntheticChildrenSP entry; 3513 3514 SyntheticScriptProvider* impl = new SyntheticScriptProvider(m_options.m_cascade, 3515 m_options.m_skip_pointers, 3516 m_options.m_skip_references, 3517 m_options.m_class_name); 3518 3519 entry.reset(impl); 3520 3521 // now I have a valid provider, let's add it to every type 3522 3523 lldb::FormatCategorySP category; 3524 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 3525 3526 Error error; 3527 3528 for (size_t i = 0; i < argc; i++) 3529 { 3530 const char* typeA = command.GetArgumentAtIndex(i); 3531 ConstString typeCS(typeA); 3532 if (typeCS) 3533 { 3534 if (!AddSynth(typeCS, 3535 entry, 3536 m_options.m_regex ? eRegexSynth : eRegularSynth, 3537 m_options.m_category, 3538 &error)) 3539 { 3540 result.AppendError(error.AsCString()); 3541 result.SetStatus(eReturnStatusFailed); 3542 return false; 3543 } 3544 } 3545 else 3546 { 3547 result.AppendError("empty typenames not allowed"); 3548 result.SetStatus(eReturnStatusFailed); 3549 return false; 3550 } 3551 } 3552 3553 result.SetStatus(eReturnStatusSuccessFinishNoResult); 3554 return result.Succeeded(); 3555 } 3556 3557 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) : 3558 CommandObject (interpreter, 3559 "type synthetic add", 3560 "Add a new synthetic provider for a type.", 3561 NULL), m_options (interpreter) 3562 { 3563 CommandArgumentEntry type_arg; 3564 CommandArgumentData type_style_arg; 3565 3566 type_style_arg.arg_type = eArgTypeName; 3567 type_style_arg.arg_repetition = eArgRepeatPlus; 3568 3569 type_arg.push_back (type_style_arg); 3570 3571 m_arguments.push_back (type_arg); 3572 3573 } 3574 3575 bool 3576 CommandObjectTypeSynthAdd::AddSynth(const ConstString& type_name, 3577 SyntheticChildrenSP entry, 3578 SynthFormatType type, 3579 std::string category_name, 3580 Error* error) 3581 { 3582 lldb::FormatCategorySP category; 3583 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); 3584 3585 if (category->AnyMatches(type_name, 3586 eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, 3587 false)) 3588 { 3589 if (error) 3590 error->SetErrorStringWithFormat("cannot add synthetic for type %s when filter is defined in same category!", type_name.AsCString()); 3591 return false; 3592 } 3593 3594 if (type == eRegexSynth) 3595 { 3596 RegularExpressionSP typeRX(new RegularExpression()); 3597 if (!typeRX->Compile(type_name.GetCString())) 3598 { 3599 if (error) 3600 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 3601 return false; 3602 } 3603 3604 category->GetRegexSyntheticNavigator()->Delete(type_name); 3605 category->GetRegexSyntheticNavigator()->Add(typeRX, entry); 3606 3607 return true; 3608 } 3609 else 3610 { 3611 category->GetSyntheticNavigator()->Add(type_name, entry); 3612 return true; 3613 } 3614 } 3615 3616 bool 3617 CommandObjectTypeSynthAdd::Execute (Args& command, CommandReturnObject &result) 3618 { 3619 if (m_options.handwrite_python) 3620 return Execute_HandwritePython(command, result); 3621 else if (m_options.is_class_based) 3622 return Execute_PythonClass(command, result); 3623 else 3624 { 3625 result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line"); 3626 result.SetStatus(eReturnStatusFailed); 3627 return false; 3628 } 3629 } 3630 3631 OptionDefinition 3632 CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] = 3633 { 3634 { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade to derived typedefs."}, 3635 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 3636 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 3637 { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 3638 { LLDB_OPT_SET_2, false, "python-class", 'l', required_argument, NULL, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children."}, 3639 { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children."}, 3640 { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, 3641 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 3642 }; 3643 3644 #endif // #ifndef LLDB_DISABLE_PYTHON 3645 3646 class CommandObjectTypeFilterAdd : public CommandObject 3647 { 3648 3649 private: 3650 3651 class CommandOptions : public Options 3652 { 3653 typedef std::vector<std::string> option_vector; 3654 public: 3655 3656 CommandOptions (CommandInterpreter &interpreter) : 3657 Options (interpreter) 3658 { 3659 } 3660 3661 virtual 3662 ~CommandOptions (){} 3663 3664 virtual Error 3665 SetOptionValue (uint32_t option_idx, const char *option_arg) 3666 { 3667 Error error; 3668 char short_option = (char) m_getopt_table[option_idx].val; 3669 bool success; 3670 3671 switch (short_option) 3672 { 3673 case 'C': 3674 m_cascade = Args::StringToBoolean(option_arg, true, &success); 3675 if (!success) 3676 error.SetErrorStringWithFormat("invalid value for cascade: %s", option_arg); 3677 break; 3678 case 'c': 3679 m_expr_paths.push_back(option_arg); 3680 has_child_list = true; 3681 break; 3682 case 'p': 3683 m_skip_pointers = true; 3684 break; 3685 case 'r': 3686 m_skip_references = true; 3687 break; 3688 case 'w': 3689 m_category = std::string(option_arg); 3690 break; 3691 case 'x': 3692 m_regex = true; 3693 break; 3694 default: 3695 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 3696 break; 3697 } 3698 3699 return error; 3700 } 3701 3702 void 3703 OptionParsingStarting () 3704 { 3705 m_cascade = true; 3706 m_skip_pointers = false; 3707 m_skip_references = false; 3708 m_category = "default"; 3709 m_expr_paths.clear(); 3710 has_child_list = false; 3711 m_regex = false; 3712 } 3713 3714 const OptionDefinition* 3715 GetDefinitions () 3716 { 3717 return g_option_table; 3718 } 3719 3720 // Options table: Required for subclasses of Options. 3721 3722 static OptionDefinition g_option_table[]; 3723 3724 // Instance variables to hold the values for command options. 3725 3726 bool m_cascade; 3727 bool m_skip_references; 3728 bool m_skip_pointers; 3729 bool m_input_python; 3730 option_vector m_expr_paths; 3731 std::string m_category; 3732 3733 bool has_child_list; 3734 3735 bool m_regex; 3736 3737 typedef option_vector::iterator ExpressionPathsIterator; 3738 }; 3739 3740 CommandOptions m_options; 3741 3742 virtual Options * 3743 GetOptions () 3744 { 3745 return &m_options; 3746 } 3747 3748 enum FilterFormatType 3749 { 3750 eRegularFilter, 3751 eRegexFilter 3752 }; 3753 3754 bool 3755 AddFilter(const ConstString& type_name, 3756 SyntheticChildrenSP entry, 3757 FilterFormatType type, 3758 std::string category_name, 3759 Error* error) 3760 { 3761 lldb::FormatCategorySP category; 3762 DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category); 3763 3764 if (category->AnyMatches(type_name, 3765 eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, 3766 false)) 3767 { 3768 if (error) 3769 error->SetErrorStringWithFormat("cannot add filter for type %s when synthetic is defined in same category!", type_name.AsCString()); 3770 return false; 3771 } 3772 3773 if (type == eRegexFilter) 3774 { 3775 RegularExpressionSP typeRX(new RegularExpression()); 3776 if (!typeRX->Compile(type_name.GetCString())) 3777 { 3778 if (error) 3779 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 3780 return false; 3781 } 3782 3783 category->GetRegexFilterNavigator()->Delete(type_name); 3784 category->GetRegexFilterNavigator()->Add(typeRX, entry); 3785 3786 return true; 3787 } 3788 else 3789 { 3790 category->GetFilterNavigator()->Add(type_name, entry); 3791 return true; 3792 } 3793 } 3794 3795 3796 public: 3797 3798 CommandObjectTypeFilterAdd (CommandInterpreter &interpreter) : 3799 CommandObject (interpreter, 3800 "type filter add", 3801 "Add a new filter for a type.", 3802 NULL), 3803 m_options (interpreter) 3804 { 3805 CommandArgumentEntry type_arg; 3806 CommandArgumentData type_style_arg; 3807 3808 type_style_arg.arg_type = eArgTypeName; 3809 type_style_arg.arg_repetition = eArgRepeatPlus; 3810 3811 type_arg.push_back (type_style_arg); 3812 3813 m_arguments.push_back (type_arg); 3814 3815 SetHelpLong( 3816 "Some examples of using this command.\n" 3817 "We use as reference the following snippet of code:\n" 3818 "\n" 3819 "class Foo {;\n" 3820 " int a;\n" 3821 " int b;\n" 3822 " int c;\n" 3823 " int d;\n" 3824 " int e;\n" 3825 " int f;\n" 3826 " int g;\n" 3827 " int h;\n" 3828 " int i;\n" 3829 "} \n" 3830 "Typing:\n" 3831 "type filter add --child a -- child g Foo\n" 3832 "frame variable a_foo\n" 3833 "will produce an output where only a and b are displayed\n" 3834 "Other children of a_foo (b,c,d,e,f,h and i) are available by asking for them, as in:\n" 3835 "frame variable a_foo.b a_foo.c ... a_foo.i\n" 3836 "\n" 3837 "Use option --raw to frame variable prevails on the filter\n" 3838 "frame variable a_foo --raw\n" 3839 "shows all the children of a_foo (a thru i) as if no filter was defined\n" 3840 ); 3841 } 3842 3843 ~CommandObjectTypeFilterAdd () 3844 { 3845 } 3846 3847 bool 3848 Execute (Args& command, CommandReturnObject &result) 3849 { 3850 const size_t argc = command.GetArgumentCount(); 3851 3852 if (argc < 1) 3853 { 3854 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 3855 result.SetStatus(eReturnStatusFailed); 3856 return false; 3857 } 3858 3859 if (m_options.m_expr_paths.size() == 0) 3860 { 3861 result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str()); 3862 result.SetStatus(eReturnStatusFailed); 3863 return false; 3864 } 3865 3866 SyntheticChildrenSP entry; 3867 3868 SyntheticFilter* impl = new SyntheticFilter(m_options.m_cascade, 3869 m_options.m_skip_pointers, 3870 m_options.m_skip_references); 3871 3872 entry.reset(impl); 3873 3874 // go through the expression paths 3875 CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end(); 3876 3877 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++) 3878 impl->AddExpressionPath(*begin); 3879 3880 3881 // now I have a valid provider, let's add it to every type 3882 3883 lldb::FormatCategorySP category; 3884 DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); 3885 3886 Error error; 3887 3888 for (size_t i = 0; i < argc; i++) 3889 { 3890 const char* typeA = command.GetArgumentAtIndex(i); 3891 ConstString typeCS(typeA); 3892 if (typeCS) 3893 { 3894 if (!AddFilter(typeCS, 3895 entry, 3896 m_options.m_regex ? eRegexFilter : eRegularFilter, 3897 m_options.m_category, 3898 &error)) 3899 { 3900 result.AppendError(error.AsCString()); 3901 result.SetStatus(eReturnStatusFailed); 3902 return false; 3903 } 3904 } 3905 else 3906 { 3907 result.AppendError("empty typenames not allowed"); 3908 result.SetStatus(eReturnStatusFailed); 3909 return false; 3910 } 3911 } 3912 3913 result.SetStatus(eReturnStatusSuccessFinishNoResult); 3914 return result.Succeeded(); 3915 } 3916 3917 }; 3918 3919 OptionDefinition 3920 CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] = 3921 { 3922 { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade to derived typedefs."}, 3923 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 3924 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 3925 { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 3926 { LLDB_OPT_SET_ALL, false, "child", 'c', required_argument, NULL, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view."}, 3927 { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, 3928 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 3929 }; 3930 3931 class CommandObjectTypeFormat : public CommandObjectMultiword 3932 { 3933 public: 3934 CommandObjectTypeFormat (CommandInterpreter &interpreter) : 3935 CommandObjectMultiword (interpreter, 3936 "type format", 3937 "A set of commands for editing variable value display options", 3938 "type format [<sub-command-options>] ") 3939 { 3940 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter))); 3941 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFormatClear (interpreter))); 3942 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter))); 3943 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFormatList (interpreter))); 3944 } 3945 3946 3947 ~CommandObjectTypeFormat () 3948 { 3949 } 3950 }; 3951 3952 #ifndef LLDB_DISABLE_PYTHON 3953 3954 class CommandObjectTypeSynth : public CommandObjectMultiword 3955 { 3956 public: 3957 CommandObjectTypeSynth (CommandInterpreter &interpreter) : 3958 CommandObjectMultiword (interpreter, 3959 "type synthetic", 3960 "A set of commands for operating on synthetic type representations", 3961 "type synthetic [<sub-command-options>] ") 3962 { 3963 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSynthAdd (interpreter))); 3964 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSynthClear (interpreter))); 3965 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSynthDelete (interpreter))); 3966 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSynthList (interpreter))); 3967 } 3968 3969 3970 ~CommandObjectTypeSynth () 3971 { 3972 } 3973 }; 3974 3975 #endif // #ifndef LLDB_DISABLE_PYTHON 3976 3977 class CommandObjectTypeFilter : public CommandObjectMultiword 3978 { 3979 public: 3980 CommandObjectTypeFilter (CommandInterpreter &interpreter) : 3981 CommandObjectMultiword (interpreter, 3982 "type filter", 3983 "A set of commands for operating on type filters", 3984 "type synthetic [<sub-command-options>] ") 3985 { 3986 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeFilterAdd (interpreter))); 3987 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFilterClear (interpreter))); 3988 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFilterDelete (interpreter))); 3989 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFilterList (interpreter))); 3990 } 3991 3992 3993 ~CommandObjectTypeFilter () 3994 { 3995 } 3996 }; 3997 3998 class CommandObjectTypeCategory : public CommandObjectMultiword 3999 { 4000 public: 4001 CommandObjectTypeCategory (CommandInterpreter &interpreter) : 4002 CommandObjectMultiword (interpreter, 4003 "type category", 4004 "A set of commands for operating on categories", 4005 "type category [<sub-command-options>] ") 4006 { 4007 LoadSubCommand ("enable", CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter))); 4008 LoadSubCommand ("disable", CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter))); 4009 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter))); 4010 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeCategoryList (interpreter))); 4011 } 4012 4013 4014 ~CommandObjectTypeCategory () 4015 { 4016 } 4017 }; 4018 4019 class CommandObjectTypeSummary : public CommandObjectMultiword 4020 { 4021 public: 4022 CommandObjectTypeSummary (CommandInterpreter &interpreter) : 4023 CommandObjectMultiword (interpreter, 4024 "type summary", 4025 "A set of commands for editing variable summary display options", 4026 "type summary [<sub-command-options>] ") 4027 { 4028 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter))); 4029 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter))); 4030 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter))); 4031 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); 4032 } 4033 4034 4035 ~CommandObjectTypeSummary () 4036 { 4037 } 4038 }; 4039 4040 //------------------------------------------------------------------------- 4041 // CommandObjectType 4042 //------------------------------------------------------------------------- 4043 4044 CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) : 4045 CommandObjectMultiword (interpreter, 4046 "type", 4047 "A set of commands for operating on the type system", 4048 "type [<sub-command-options>]") 4049 { 4050 LoadSubCommand ("category", CommandObjectSP (new CommandObjectTypeCategory (interpreter))); 4051 LoadSubCommand ("filter", CommandObjectSP (new CommandObjectTypeFilter (interpreter))); 4052 LoadSubCommand ("format", CommandObjectSP (new CommandObjectTypeFormat (interpreter))); 4053 LoadSubCommand ("summary", CommandObjectSP (new CommandObjectTypeSummary (interpreter))); 4054 #ifndef LLDB_DISABLE_PYTHON 4055 LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter))); 4056 #endif 4057 } 4058 4059 4060 CommandObjectType::~CommandObjectType () 4061 { 4062 } 4063 4064 4065