CommandObjectType.cpp revision 1e620f0c6b953f86436a97fdd1d728648b4cdab1
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// C++ Includes 14 15#include "lldb/Core/ConstString.h" 16#include "lldb/Core/Debugger.h" 17#include "lldb/Core/FormatManager.h" 18#include "lldb/Core/InputReaderEZ.h" 19#include "lldb/Core/RegularExpression.h" 20#include "lldb/Core/State.h" 21#include "lldb/Core/StringList.h" 22#include "lldb/Interpreter/CommandInterpreter.h" 23#include "lldb/Interpreter/CommandObject.h" 24#include "lldb/Interpreter/CommandReturnObject.h" 25#include "lldb/Interpreter/Options.h" 26 27using namespace lldb; 28using namespace lldb_private; 29 30//------------------------------------------------------------------------- 31// CommandObjectTypeFormatAdd 32//------------------------------------------------------------------------- 33 34class CommandObjectTypeFormatAdd : public CommandObject 35{ 36 37private: 38 39 class CommandOptions : public Options 40 { 41 public: 42 43 CommandOptions (CommandInterpreter &interpreter) : 44 Options (interpreter) 45 { 46 } 47 48 virtual 49 ~CommandOptions (){} 50 51 virtual Error 52 SetOptionValue (uint32_t option_idx, const char *option_arg) 53 { 54 Error error; 55 char short_option = (char) m_getopt_table[option_idx].val; 56 bool success; 57 58 switch (short_option) 59 { 60 case 'C': 61 m_cascade = Args::StringToBoolean(option_arg, true, &success); 62 if (!success) 63 error.SetErrorStringWithFormat("Invalid value for cascade: %s.\n", option_arg); 64 break; 65 case 'f': 66 error = Args::StringToFormat(option_arg, m_format, NULL); 67 break; 68 case 'p': 69 m_skip_pointers = true; 70 break; 71 case 'r': 72 m_skip_references = true; 73 break; 74 default: 75 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 76 break; 77 } 78 79 return error; 80 } 81 82 void 83 OptionParsingStarting () 84 { 85 m_cascade = true; 86 m_format = eFormatInvalid; 87 m_skip_pointers = false; 88 m_skip_references = false; 89 } 90 91 const OptionDefinition* 92 GetDefinitions () 93 { 94 return g_option_table; 95 } 96 97 // Options table: Required for subclasses of Options. 98 99 static OptionDefinition g_option_table[]; 100 101 // Instance variables to hold the values for command options. 102 103 bool m_cascade; 104 lldb::Format m_format; 105 bool m_skip_references; 106 bool m_skip_pointers; 107 }; 108 109 CommandOptions m_options; 110 111 virtual Options * 112 GetOptions () 113 { 114 return &m_options; 115 } 116 117public: 118 CommandObjectTypeFormatAdd (CommandInterpreter &interpreter) : 119 CommandObject (interpreter, 120 "type format add", 121 "Add a new formatting style for a type.", 122 NULL), m_options (interpreter) 123 { 124 CommandArgumentEntry type_arg; 125 CommandArgumentData type_style_arg; 126 127 type_style_arg.arg_type = eArgTypeName; 128 type_style_arg.arg_repetition = eArgRepeatPlus; 129 130 type_arg.push_back (type_style_arg); 131 132 m_arguments.push_back (type_arg); 133 134 SetHelpLong( 135 "Some examples of using this command.\n" 136 "We use as reference the following snippet of code:\n" 137 "\n" 138 "typedef int Aint;\n" 139 "typedef float Afloat;\n" 140 "typedef Aint Bint;\n" 141 "typedef Afloat Bfloat;\n" 142 "\n" 143 "Aint ix = 5;\n" 144 "Bint iy = 5;\n" 145 "\n" 146 "Afloat fx = 3.14;\n" 147 "BFloat fy = 3.14;\n" 148 "\n" 149 "Typing:\n" 150 "type format add -f hex AInt\n" 151 "frame variable iy\n" 152 "will produce an hex display of iy, because no formatter is available for Bint and the one for Aint is used instead\n" 153 "To prevent this type\n" 154 "type format add -f hex -C no AInt\n" 155 "\n" 156 "A similar reasoning applies to\n" 157 "type format add -f hex -C no float -p\n" 158 "which now prints all floats and float&s as hexadecimal, but does not format float*s\n" 159 "and does not change the default display for Afloat and Bfloat objects.\n" 160 ); 161 } 162 163 ~CommandObjectTypeFormatAdd () 164 { 165 } 166 167 bool 168 Execute (Args& command, CommandReturnObject &result) 169 { 170 const size_t argc = command.GetArgumentCount(); 171 172 if (argc < 1) 173 { 174 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 175 result.SetStatus(eReturnStatusFailed); 176 return false; 177 } 178 179 if (m_options.m_format == eFormatInvalid) 180 { 181 result.AppendErrorWithFormat ("%s needs a valid format.\n", m_cmd_name.c_str()); 182 result.SetStatus(eReturnStatusFailed); 183 return false; 184 } 185 186 ValueFormatSP entry; 187 188 entry.reset(new ValueFormat(m_options.m_format, 189 m_options.m_cascade, 190 m_options.m_skip_pointers, 191 m_options.m_skip_references)); 192 193 // now I have a valid format, let's add it to every type 194 195 for (size_t i = 0; i < argc; i++) { 196 const char* typeA = command.GetArgumentAtIndex(i); 197 ConstString typeCS(typeA); 198 if (typeCS) 199 Debugger::Formatting::ValueFormats::Add(typeCS, entry); 200 else 201 { 202 result.AppendError("empty typenames not allowed"); 203 result.SetStatus(eReturnStatusFailed); 204 return false; 205 } 206 } 207 208 result.SetStatus(eReturnStatusSuccessFinishNoResult); 209 return result.Succeeded(); 210 } 211}; 212 213OptionDefinition 214CommandObjectTypeFormatAdd::CommandOptions::g_option_table[] = 215{ 216 { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade to derived typedefs."}, 217 { LLDB_OPT_SET_ALL, false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat, "The format to use to display this type."}, 218 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeBoolean, "Don't use this format for pointers-to-type objects."}, 219 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeBoolean, "Don't use this format for references-to-type objects."}, 220 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 221}; 222 223 224//------------------------------------------------------------------------- 225// CommandObjectTypeFormatDelete 226//------------------------------------------------------------------------- 227 228class CommandObjectTypeFormatDelete : public CommandObject 229{ 230public: 231 CommandObjectTypeFormatDelete (CommandInterpreter &interpreter) : 232 CommandObject (interpreter, 233 "type format delete", 234 "Delete an existing formatting style for a type.", 235 NULL) 236 { 237 CommandArgumentEntry type_arg; 238 CommandArgumentData type_style_arg; 239 240 type_style_arg.arg_type = eArgTypeName; 241 type_style_arg.arg_repetition = eArgRepeatPlain; 242 243 type_arg.push_back (type_style_arg); 244 245 m_arguments.push_back (type_arg); 246 247 } 248 249 ~CommandObjectTypeFormatDelete () 250 { 251 } 252 253 bool 254 Execute (Args& command, CommandReturnObject &result) 255 { 256 const size_t argc = command.GetArgumentCount(); 257 258 if (argc != 1) 259 { 260 result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); 261 result.SetStatus(eReturnStatusFailed); 262 return false; 263 } 264 265 const char* typeA = command.GetArgumentAtIndex(0); 266 ConstString typeCS(typeA); 267 268 if (!typeCS) 269 { 270 result.AppendError("empty typenames not allowed"); 271 result.SetStatus(eReturnStatusFailed); 272 return false; 273 } 274 275 276 if (Debugger::Formatting::ValueFormats::Delete(typeCS)) 277 { 278 result.SetStatus(eReturnStatusSuccessFinishNoResult); 279 return result.Succeeded(); 280 } 281 else 282 { 283 result.AppendErrorWithFormat ("no custom format for %s.\n", typeA); 284 result.SetStatus(eReturnStatusFailed); 285 return false; 286 } 287 288 } 289 290}; 291 292//------------------------------------------------------------------------- 293// CommandObjectTypeFormatClear 294//------------------------------------------------------------------------- 295 296class CommandObjectTypeFormatClear : public CommandObject 297{ 298public: 299 CommandObjectTypeFormatClear (CommandInterpreter &interpreter) : 300 CommandObject (interpreter, 301 "type format clear", 302 "Delete all existing format styles.", 303 NULL) 304 { 305 } 306 307 ~CommandObjectTypeFormatClear () 308 { 309 } 310 311 bool 312 Execute (Args& command, CommandReturnObject &result) 313 { 314 Debugger::Formatting::ValueFormats::Clear(); 315 result.SetStatus(eReturnStatusSuccessFinishResult); 316 return result.Succeeded(); 317 } 318 319}; 320 321//------------------------------------------------------------------------- 322// CommandObjectTypeFormatList 323//------------------------------------------------------------------------- 324 325bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, const char* type, const ValueFormat::SharedPointer& entry); 326 327class CommandObjectTypeFormatList; 328 329struct CommandObjectTypeFormatList_LoopCallbackParam { 330 CommandObjectTypeFormatList* self; 331 CommandReturnObject* result; 332 RegularExpression* regex; 333 CommandObjectTypeFormatList_LoopCallbackParam(CommandObjectTypeFormatList* S, CommandReturnObject* R, 334 RegularExpression* X = NULL) : self(S), result(R), regex(X) {} 335}; 336 337class CommandObjectTypeFormatList : public CommandObject 338{ 339public: 340 CommandObjectTypeFormatList (CommandInterpreter &interpreter) : 341 CommandObject (interpreter, 342 "type format list", 343 "Show a list of current formatting styles.", 344 NULL) 345 { 346 CommandArgumentEntry type_arg; 347 CommandArgumentData type_style_arg; 348 349 type_style_arg.arg_type = eArgTypeName; 350 type_style_arg.arg_repetition = eArgRepeatOptional; 351 352 type_arg.push_back (type_style_arg); 353 354 m_arguments.push_back (type_arg); 355 } 356 357 ~CommandObjectTypeFormatList () 358 { 359 } 360 361 bool 362 Execute (Args& command, CommandReturnObject &result) 363 { 364 const size_t argc = command.GetArgumentCount(); 365 366 CommandObjectTypeFormatList_LoopCallbackParam *param; 367 368 if (argc == 1) { 369 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 370 regex->Compile(command.GetArgumentAtIndex(0)); 371 param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result,regex); 372 } 373 else 374 param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result); 375 Debugger::Formatting::ValueFormats::LoopThrough(CommandObjectTypeFormatList_LoopCallback, param); 376 delete param; 377 result.SetStatus(eReturnStatusSuccessFinishResult); 378 return result.Succeeded(); 379 } 380 381private: 382 383 bool 384 LoopCallback (const char* type, 385 const ValueFormat::SharedPointer& entry, 386 RegularExpression* regex, 387 CommandReturnObject *result) 388 { 389 if (regex == NULL || regex->Execute(type)) 390 { 391 result->GetOutputStream().Printf ("%s: %s%s%s%s\n", type, 392 FormatManager::GetFormatAsCString (entry->m_format), 393 entry->m_cascades ? "" : " (not cascading)", 394 entry->m_skip_pointers ? " (skip pointers)" : "", 395 entry->m_skip_references ? " (skip references)" : ""); 396 } 397 return true; 398 } 399 400 friend bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, const char* type, const ValueFormat::SharedPointer& entry); 401 402}; 403 404bool 405CommandObjectTypeFormatList_LoopCallback ( 406 void* pt2self, 407 const char* type, 408 const ValueFormat::SharedPointer& entry) 409{ 410 CommandObjectTypeFormatList_LoopCallbackParam* param = (CommandObjectTypeFormatList_LoopCallbackParam*)pt2self; 411 return param->self->LoopCallback(type, entry, param->regex, param->result); 412} 413 414 415 416 417//------------------------------------------------------------------------- 418// CommandObjectTypeSummaryAdd 419//------------------------------------------------------------------------- 420 421static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" 422 "def function (valobj,dict):"; 423 424class TypeScriptAddInputReader : public InputReaderEZ 425{ 426private: 427 DISALLOW_COPY_AND_ASSIGN (TypeScriptAddInputReader); 428public: 429 TypeScriptAddInputReader(Debugger& debugger) : 430 InputReaderEZ(debugger) 431 {} 432 433 virtual 434 ~TypeScriptAddInputReader() 435 { 436 } 437 438 virtual void ActivateHandler(HandlerData& data) 439 { 440 StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); 441 bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); 442 if (!batch_mode) 443 { 444 out_stream->Printf ("%s\n", g_reader_instructions); 445 if (data.reader.GetPrompt()) 446 out_stream->Printf ("%s", data.reader.GetPrompt()); 447 out_stream->Flush(); 448 } 449 } 450 451 virtual void ReactivateHandler(HandlerData& data) 452 { 453 StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); 454 bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); 455 if (data.reader.GetPrompt() && !batch_mode) 456 { 457 out_stream->Printf ("%s", data.reader.GetPrompt()); 458 out_stream->Flush(); 459 } 460 } 461 virtual void GotTokenHandler(HandlerData& data) 462 { 463 StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); 464 bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); 465 if (data.bytes && data.bytes_len && data.baton) 466 { 467 ((ScriptAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len); 468 } 469 if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode) 470 { 471 out_stream->Printf ("%s", data.reader.GetPrompt()); 472 out_stream->Flush(); 473 } 474 } 475 virtual void InterruptHandler(HandlerData& data) 476 { 477 StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); 478 bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); 479 data.reader.SetIsDone (true); 480 if (!batch_mode) 481 { 482 out_stream->Printf ("Warning: No command attached to breakpoint.\n"); 483 out_stream->Flush(); 484 } 485 } 486 virtual void EOFHandler(HandlerData& data) 487 { 488 data.reader.SetIsDone (true); 489 } 490 virtual void DoneHandler(HandlerData& data) 491 { 492 StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); 493 ScriptAddOptions *options_ptr = ((ScriptAddOptions*)data.baton); 494 if (!options_ptr) 495 { 496 out_stream->Printf ("Internal error #1: no script attached.\n"); 497 out_stream->Flush(); 498 return; 499 } 500 501 ScriptAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope 502 503 ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 504 if (!interpreter) 505 { 506 out_stream->Printf ("Internal error #2: no script attached.\n"); 507 out_stream->Flush(); 508 return; 509 } 510 StringList funct_name_sl; 511 if (!interpreter->GenerateTypeScriptFunction (options->m_user_source, 512 funct_name_sl)) 513 { 514 out_stream->Printf ("Internal error #3: no script attached.\n"); 515 out_stream->Flush(); 516 return; 517 } 518 if (funct_name_sl.GetSize() == 0) 519 { 520 out_stream->Printf ("Internal error #4: no script attached.\n"); 521 out_stream->Flush(); 522 return; 523 } 524 const char *funct_name = funct_name_sl.GetStringAtIndex(0); 525 if (!funct_name || !funct_name[0]) 526 { 527 out_stream->Printf ("Internal error #5: no script attached.\n"); 528 out_stream->Flush(); 529 return; 530 } 531 // now I have a valid function name, let's add this as script for every type in the list 532 533 SummaryFormatSP script_format; 534 script_format.reset(new ScriptSummaryFormat(options->m_cascade, 535 options->m_skip_pointers, 536 options->m_skip_references, 537 options->m_no_children, 538 options->m_no_value, 539 options->m_one_liner, 540 std::string(funct_name), 541 options->m_user_source.CopyList(" "))); 542 543 Error error; 544 545 for (size_t i = 0; i < options->m_target_types.GetSize(); i++) 546 { 547 const char *type_name = options->m_target_types.GetStringAtIndex(i); 548 CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name), 549 script_format, 550 (options->m_regex ? CommandObjectTypeSummaryAdd::eRegexSummary : CommandObjectTypeSummaryAdd::eRegularSummary), 551 options->m_category, 552 &error); 553 if (error.Fail()) 554 { 555 out_stream->Printf (error.AsCString()); 556 out_stream->Flush(); 557 return; 558 } 559 } 560 561 if (options->m_name) 562 { 563 if ( (bool)(*(options->m_name)) ) 564 { 565 CommandObjectTypeSummaryAdd::AddSummary(*(options->m_name), 566 script_format, 567 CommandObjectTypeSummaryAdd::eNamedSummary, 568 options->m_category, 569 &error); 570 if (error.Fail()) 571 { 572 out_stream->Printf (error.AsCString()); 573 out_stream->Flush(); 574 return; 575 } 576 } 577 else 578 { 579 out_stream->Printf (error.AsCString()); 580 out_stream->Flush(); 581 return; 582 } 583 } 584 } 585}; 586 587Error 588CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) 589{ 590 Error error; 591 char short_option = (char) m_getopt_table[option_idx].val; 592 bool success; 593 594 switch (short_option) 595 { 596 case 'C': 597 m_cascade = Args::StringToBoolean(option_arg, true, &success); 598 if (!success) 599 error.SetErrorStringWithFormat("Invalid value for cascade: %s.\n", option_arg); 600 break; 601 case 'e': 602 m_no_children = false; 603 break; 604 case 'v': 605 m_no_value = true; 606 break; 607 case 'c': 608 m_one_liner = true; 609 break; 610 case 'f': 611 m_format_string = std::string(option_arg); 612 break; 613 case 'p': 614 m_skip_pointers = true; 615 break; 616 case 'r': 617 m_skip_references = true; 618 break; 619 case 'x': 620 m_regex = true; 621 break; 622 case 'n': 623 m_name = new ConstString(option_arg); 624 break; 625 case 's': 626 m_python_script = std::string(option_arg); 627 m_is_add_script = true; 628 break; 629 case 'F': 630 m_python_function = std::string(option_arg); 631 m_is_add_script = true; 632 break; 633 case 'P': 634 m_is_add_script = true; 635 break; 636 case 'w': 637 m_category = ConstString(option_arg).GetCString(); 638 break; 639 default: 640 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 641 break; 642 } 643 644 return error; 645} 646 647void 648CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting () 649{ 650 m_cascade = true; 651 m_no_children = true; 652 m_no_value = false; 653 m_one_liner = false; 654 m_skip_references = false; 655 m_skip_pointers = false; 656 m_regex = false; 657 m_name = NULL; 658 m_python_script = ""; 659 m_python_function = ""; 660 m_is_add_script = false; 661 m_category = NULL; 662} 663 664void 665CommandObjectTypeSummaryAdd::CollectPythonScript (ScriptAddOptions *options, 666 CommandReturnObject &result) 667{ 668 InputReaderSP reader_sp (new TypeScriptAddInputReader(m_interpreter.GetDebugger())); 669 if (reader_sp && options) 670 { 671 672 InputReaderEZ::InitializationParameters ipr; 673 674 Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt(" "))); 675 if (err.Success()) 676 { 677 m_interpreter.GetDebugger().PushInputReader (reader_sp); 678 result.SetStatus (eReturnStatusSuccessFinishNoResult); 679 } 680 else 681 { 682 result.AppendError (err.AsCString()); 683 result.SetStatus (eReturnStatusFailed); 684 } 685 } 686 else 687 { 688 result.AppendError("out of memory"); 689 result.SetStatus (eReturnStatusFailed); 690 } 691 692} 693 694bool 695CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturnObject &result) 696{ 697 const size_t argc = command.GetArgumentCount(); 698 699 if (argc < 1 && !m_options.m_name) 700 { 701 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 702 result.SetStatus(eReturnStatusFailed); 703 return false; 704 } 705 706 SummaryFormatSP script_format; 707 708 if (!m_options.m_python_function.empty()) // we have a Python function ready to use 709 { 710 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 711 if (!interpreter) 712 { 713 result.AppendError ("Internal error #1N: no script attached.\n"); 714 result.SetStatus (eReturnStatusFailed); 715 return false; 716 } 717 const char *funct_name = m_options.m_python_function.c_str(); 718 if (!funct_name || !funct_name[0]) 719 { 720 result.AppendError ("Internal error #2N: no script attached.\n"); 721 result.SetStatus (eReturnStatusFailed); 722 return false; 723 } 724 725 script_format.reset(new ScriptSummaryFormat(m_options.m_cascade, 726 m_options.m_skip_pointers, 727 m_options.m_skip_references, 728 m_options.m_no_children, 729 m_options.m_no_value, 730 m_options.m_one_liner, 731 std::string(funct_name), 732 " " + m_options.m_python_function + "(valobj,dict)")); 733 } 734 else if (!m_options.m_python_script.empty()) // we have a quick 1-line script, just use it 735 { 736 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); 737 if (!interpreter) 738 { 739 result.AppendError ("Internal error #1Q: no script attached.\n"); 740 result.SetStatus (eReturnStatusFailed); 741 return false; 742 } 743 StringList funct_sl; 744 funct_sl << m_options.m_python_script.c_str(); 745 StringList funct_name_sl; 746 if (!interpreter->GenerateTypeScriptFunction (funct_sl, 747 funct_name_sl)) 748 { 749 result.AppendError ("Internal error #2Q: no script attached.\n"); 750 result.SetStatus (eReturnStatusFailed); 751 return false; 752 } 753 if (funct_name_sl.GetSize() == 0) 754 { 755 result.AppendError ("Internal error #3Q: no script attached.\n"); 756 result.SetStatus (eReturnStatusFailed); 757 return false; 758 } 759 const char *funct_name = funct_name_sl.GetStringAtIndex(0); 760 if (!funct_name || !funct_name[0]) 761 { 762 result.AppendError ("Internal error #4Q: no script attached.\n"); 763 result.SetStatus (eReturnStatusFailed); 764 return false; 765 } 766 767 script_format.reset(new ScriptSummaryFormat(m_options.m_cascade, 768 m_options.m_skip_pointers, 769 m_options.m_skip_references, 770 m_options.m_no_children, 771 m_options.m_no_value, 772 m_options.m_one_liner, 773 std::string(funct_name), 774 " " + m_options.m_python_script)); 775 } 776 else // use an InputReader to grab Python code from the user 777 { 778 ScriptAddOptions *options = new ScriptAddOptions(m_options.m_skip_pointers, 779 m_options.m_skip_references, 780 m_options.m_cascade, 781 m_options.m_no_children, 782 m_options.m_no_value, 783 m_options.m_one_liner, 784 m_options.m_regex, 785 m_options.m_name, 786 m_options.m_category); 787 788 for (size_t i = 0; i < argc; i++) { 789 const char* typeA = command.GetArgumentAtIndex(i); 790 if (typeA && *typeA) 791 options->m_target_types << typeA; 792 else 793 { 794 result.AppendError("empty typenames not allowed"); 795 result.SetStatus(eReturnStatusFailed); 796 return false; 797 } 798 } 799 800 CollectPythonScript(options,result); 801 return result.Succeeded(); 802 } 803 804 // if I am here, script_format must point to something good, so I can add that 805 // as a script summary to all interested parties 806 807 Error error; 808 809 for (size_t i = 0; i < command.GetArgumentCount(); i++) 810 { 811 const char *type_name = command.GetArgumentAtIndex(i); 812 CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name), 813 script_format, 814 (m_options.m_regex ? eRegexSummary : eRegularSummary), 815 m_options.m_category, 816 &error); 817 if (error.Fail()) 818 { 819 result.AppendError(error.AsCString()); 820 result.SetStatus(eReturnStatusFailed); 821 return false; 822 } 823 } 824 825 if (m_options.m_name) 826 { 827 if ( (bool)(*(m_options.m_name)) ) 828 { 829 AddSummary(*(m_options.m_name), script_format, eNamedSummary, m_options.m_category, &error); 830 if (error.Fail()) 831 { 832 result.AppendError(error.AsCString()); 833 result.AppendError("added to types, but not given a name"); 834 result.SetStatus(eReturnStatusFailed); 835 return false; 836 } 837 } 838 else 839 { 840 result.AppendError("added to types, but not given a name"); 841 result.SetStatus(eReturnStatusFailed); 842 return false; 843 } 844 } 845 846 return result.Succeeded(); 847} 848 849bool 850CommandObjectTypeSummaryAdd::Execute_StringSummary (Args& command, CommandReturnObject &result) 851{ 852 const size_t argc = command.GetArgumentCount(); 853 854 if (argc < 1 && !m_options.m_name) 855 { 856 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 857 result.SetStatus(eReturnStatusFailed); 858 return false; 859 } 860 861 if (!m_options.m_one_liner && m_options.m_format_string.empty()) 862 { 863 result.AppendError("empty summary strings not allowed"); 864 result.SetStatus(eReturnStatusFailed); 865 return false; 866 } 867 868 const char* format_cstr = (m_options.m_one_liner ? "" : m_options.m_format_string.c_str()); 869 870 Error error; 871 872 SummaryFormat::SharedPointer entry(new StringSummaryFormat(m_options.m_cascade, 873 m_options.m_skip_pointers, 874 m_options.m_skip_references, 875 m_options.m_no_children, 876 m_options.m_no_value, 877 m_options.m_one_liner, 878 format_cstr)); 879 880 if (error.Fail()) 881 { 882 result.AppendError(error.AsCString()); 883 result.SetStatus(eReturnStatusFailed); 884 return false; 885 } 886 887 // now I have a valid format, let's add it to every type 888 889 for (size_t i = 0; i < argc; i++) { 890 const char* typeA = command.GetArgumentAtIndex(i); 891 if (!typeA || typeA[0] == '\0') 892 { 893 result.AppendError("empty typenames not allowed"); 894 result.SetStatus(eReturnStatusFailed); 895 return false; 896 } 897 ConstString typeCS(typeA); 898 899 AddSummary(typeCS, 900 entry, 901 (m_options.m_regex ? eRegexSummary : eRegularSummary), 902 m_options.m_category, 903 &error); 904 905 if (error.Fail()) 906 { 907 result.AppendError(error.AsCString()); 908 result.SetStatus(eReturnStatusFailed); 909 return false; 910 } 911 } 912 913 if (m_options.m_name) 914 { 915 if ( (bool)(*(m_options.m_name)) ) 916 { 917 AddSummary(*(m_options.m_name), entry, eNamedSummary, m_options.m_category, &error); 918 if (error.Fail()) 919 { 920 result.AppendError(error.AsCString()); 921 result.AppendError("added to types, but not given a name"); 922 result.SetStatus(eReturnStatusFailed); 923 return false; 924 } 925 } 926 else 927 { 928 result.AppendError("added to types, but not given a name"); 929 result.SetStatus(eReturnStatusFailed); 930 return false; 931 } 932 } 933 934 result.SetStatus(eReturnStatusSuccessFinishNoResult); 935 return result.Succeeded(); 936} 937 938CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter) : 939CommandObject (interpreter, 940 "type summary add", 941 "Add a new summary style for a type.", 942 NULL), m_options (interpreter) 943{ 944 CommandArgumentEntry type_arg; 945 CommandArgumentData type_style_arg; 946 947 type_style_arg.arg_type = eArgTypeName; 948 type_style_arg.arg_repetition = eArgRepeatPlus; 949 950 type_arg.push_back (type_style_arg); 951 952 m_arguments.push_back (type_arg); 953 954 SetHelpLong( 955 "Some examples of using this command.\n" 956 "We use as reference the following snippet of code:\n" 957 "struct JustADemo\n" 958 "{\n" 959 "int* ptr;\n" 960 "float value;\n" 961 "JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}\n" 962 "};\n" 963 "JustADemo object(42,3.14);\n" 964 "struct AnotherDemo : public JustADemo\n" 965 "{\n" 966 "uint8_t byte;\n" 967 "AnotherDemo(uint8_t b = 'E', int p = 1, float v = 0.1) : JustADemo(p,v), byte(b) {}\n" 968 "};\n" 969 "AnotherDemo *another_object = new AnotherDemo('E',42,3.14);\n" 970 "\n" 971 "type summary add -f \"the answer is ${*var.ptr}\" JustADemo\n" 972 "when typing frame variable object you will get \"the answer is 42\"\n" 973 "type summary add -f \"the answer is ${*var.ptr}, and the question is ${var.value}\" JustADemo\n" 974 "when typing frame variable object you will get \"the answer is 42 and the question is 3.14\"\n" 975 "\n" 976 "Alternatively, you could also say\n" 977 "type summary add -f \"${var%V} -> ${*var}\" \"int *\"\n" 978 "and replace the above summary string with\n" 979 "type summary add -f \"the answer is ${var.ptr}, and the question is ${var.value}\" JustADemo\n" 980 "to obtain a similar result\n" 981 "\n" 982 "To add a summary valid for both JustADemo and AnotherDemo you can use the scoping operator, as in:\n" 983 "type summary add -f \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes\n" 984 "\n" 985 "This will be used for both variables of type JustADemo and AnotherDemo. To prevent this, change the -C to read -C no\n" 986 "If you do not want pointers to be shown using that summary, you can use the -p option, as in:\n" 987 "type summary add -f \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes -p\n" 988 "A similar option -r exists for references.\n" 989 "\n" 990 "If you simply want a one-line summary of the content of your variable, without typing an explicit string to that effect\n" 991 "you can use the -c option, without giving any summary string:\n" 992 "type summary add -c JustADemo\n" 993 "frame variable object\n" 994 "the output being similar to (ptr=0xsomeaddress, value=3.14)\n" 995 "\n" 996 "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" 997 "type summary add -e -f \"*ptr = ${*var.ptr}\" JustADemo\n" 998 "Here the value of the int* is displayed, followed by the standard LLDB sequence of children objects, one per line.\n" 999 "to get an output like:\n" 1000 "\n" 1001 "*ptr = 42 {\n" 1002 " ptr = 0xsomeaddress\n" 1003 " value = 3.14\n" 1004 "}\n" 1005 "\n" 1006 "A command you may definitely want to try if you're doing C++ debugging is:\n" 1007 "type summary add -f \"${var._M_dataplus._M_p}\" std::string\n" 1008 "\n" 1009 "You can also add Python summaries, in which case you will use lldb public API to gather information from your variables" 1010 "and elaborate them to a meaningful summary inside a script written in Python. The variable object will be passed to your" 1011 "script as an SBValue object. The following example might help you when starting to use the Python summaries feature:\n" 1012 "type summary add JustADemo -s \"value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();\"\n" 1013 "If you prefer to type your scripts on multiple lines, you will use the -P option and then type your script, ending it with " 1014 "the word DONE on a line by itself to mark you're finished editing your code:\n" 1015 "(lldb)type summary add JustADemo -P\n" 1016 " value = valobj.GetChildMemberWithName('value');\n" 1017 " return 'My value is ' + value.GetValue();\n" 1018 "DONE\n" 1019 "(lldb)" 1020 ); 1021} 1022 1023bool 1024CommandObjectTypeSummaryAdd::Execute (Args& command, CommandReturnObject &result) 1025{ 1026 if (m_options.m_is_add_script) 1027 return Execute_ScriptSummary(command, result); 1028 else 1029 return Execute_StringSummary(command, result); 1030} 1031 1032bool 1033CommandObjectTypeSummaryAdd::AddSummary(const ConstString& type_name, 1034 SummaryFormatSP entry, 1035 SummaryFormatType type, 1036 const char* category_name, 1037 Error* error) 1038{ 1039 lldb::FormatCategorySP category; 1040 Debugger::Formatting::Categories::Get(ConstString(category_name), category); 1041 1042 if (type == eRegexSummary) 1043 { 1044 RegularExpressionSP typeRX(new RegularExpression()); 1045 if (!typeRX->Compile(type_name.GetCString())) 1046 { 1047 if (error) 1048 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 1049 return false; 1050 } 1051 1052 category->RegexSummary()->Delete(type_name.GetCString()); 1053 category->RegexSummary()->Add(typeRX, entry); 1054 1055 return true; 1056 } 1057 else if (type == eNamedSummary) 1058 { 1059 // system named summaries do not exist (yet?) 1060 Debugger::Formatting::NamedSummaryFormats::Add(type_name,entry); 1061 return true; 1062 } 1063 else 1064 { 1065 category->Summary()->Add(type_name.GetCString(), entry); 1066 return true; 1067 } 1068} 1069 1070OptionDefinition 1071CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = 1072{ 1073 { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 1074 { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade to derived typedefs."}, 1075 { LLDB_OPT_SET_ALL, false, "no-value", 'v', no_argument, NULL, 0, eArgTypeBoolean, "Don't show the value, just show the summary, for this type."}, 1076 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeBoolean, "Don't use this format for pointers-to-type objects."}, 1077 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeBoolean, "Don't use this format for references-to-type objects."}, 1078 { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeBoolean, "Type names are actually regular expressions."}, 1079 { LLDB_OPT_SET_1 , true, "inline-children", 'c', no_argument, NULL, 0, eArgTypeBoolean, "If true, inline all child values into summary string."}, 1080 { LLDB_OPT_SET_2 , true, "format-string", 'f', required_argument, NULL, 0, eArgTypeSummaryString, "Format string used to display text and object contents."}, 1081 { LLDB_OPT_SET_3, false, "python-script", 's', required_argument, NULL, 0, eArgTypeName, "Give a one-liner Python script as part of the command."}, 1082 { LLDB_OPT_SET_3, false, "python-function", 'F', required_argument, NULL, 0, eArgTypeName, "Give the name of a Python function to use for this type."}, 1083 { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeName, "Input Python code to use for this type manually."}, 1084 { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', no_argument, NULL, 0, eArgTypeBoolean, "Expand aggregate data types to show children on separate lines."}, 1085 { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', required_argument, NULL, 0, eArgTypeName, "A name for this summary string."}, 1086 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1087}; 1088 1089 1090//------------------------------------------------------------------------- 1091// CommandObjectTypeSummaryDelete 1092//------------------------------------------------------------------------- 1093 1094class CommandObjectTypeSummaryDelete : public CommandObject 1095{ 1096private: 1097 class CommandOptions : public Options 1098 { 1099 public: 1100 1101 CommandOptions (CommandInterpreter &interpreter) : 1102 Options (interpreter) 1103 { 1104 } 1105 1106 virtual 1107 ~CommandOptions (){} 1108 1109 virtual Error 1110 SetOptionValue (uint32_t option_idx, const char *option_arg) 1111 { 1112 Error error; 1113 char short_option = (char) m_getopt_table[option_idx].val; 1114 1115 switch (short_option) 1116 { 1117 case 'a': 1118 m_delete_all = true; 1119 break; 1120 case 'w': 1121 m_category = ConstString(option_arg).GetCString(); 1122 break; 1123 default: 1124 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 1125 break; 1126 } 1127 1128 return error; 1129 } 1130 1131 void 1132 OptionParsingStarting () 1133 { 1134 m_delete_all = false; 1135 m_category = NULL; 1136 } 1137 1138 const OptionDefinition* 1139 GetDefinitions () 1140 { 1141 return g_option_table; 1142 } 1143 1144 // Options table: Required for subclasses of Options. 1145 1146 static OptionDefinition g_option_table[]; 1147 1148 // Instance variables to hold the values for command options. 1149 1150 bool m_delete_all; 1151 const char* m_category; 1152 1153 }; 1154 1155 CommandOptions m_options; 1156 1157 virtual Options * 1158 GetOptions () 1159 { 1160 return &m_options; 1161 } 1162 1163 static bool 1164 PerCategoryCallback(void* param, 1165 const char* cate_name, 1166 const FormatCategory::SharedPointer& cate) 1167 { 1168 const char* name = (const char*)param; 1169 cate->Summary()->Delete(name); 1170 cate->RegexSummary()->Delete(name); 1171 return true; 1172 } 1173 1174public: 1175 CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) : 1176 CommandObject (interpreter, 1177 "type summary delete", 1178 "Delete an existing summary style for a type.", 1179 NULL), m_options(interpreter) 1180 { 1181 CommandArgumentEntry type_arg; 1182 CommandArgumentData type_style_arg; 1183 1184 type_style_arg.arg_type = eArgTypeName; 1185 type_style_arg.arg_repetition = eArgRepeatPlain; 1186 1187 type_arg.push_back (type_style_arg); 1188 1189 m_arguments.push_back (type_arg); 1190 1191 } 1192 1193 ~CommandObjectTypeSummaryDelete () 1194 { 1195 } 1196 1197 bool 1198 Execute (Args& command, CommandReturnObject &result) 1199 { 1200 const size_t argc = command.GetArgumentCount(); 1201 1202 if (argc != 1) 1203 { 1204 result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); 1205 result.SetStatus(eReturnStatusFailed); 1206 return false; 1207 } 1208 1209 const char* typeA = command.GetArgumentAtIndex(0); 1210 ConstString typeCS(typeA); 1211 1212 if (!typeCS) 1213 { 1214 result.AppendError("empty typenames not allowed"); 1215 result.SetStatus(eReturnStatusFailed); 1216 return false; 1217 } 1218 1219 if (m_options.m_delete_all) 1220 { 1221 Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, (void*)typeCS.GetCString()); 1222 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1223 return result.Succeeded(); 1224 } 1225 1226 lldb::FormatCategorySP category; 1227 Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category); 1228 1229 bool delete_category = category->Delete(typeCS.GetCString()); 1230 bool delete_named = Debugger::Formatting::NamedSummaryFormats::Delete(typeCS); 1231 1232 if (delete_category || delete_named) 1233 { 1234 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1235 return result.Succeeded(); 1236 } 1237 else 1238 { 1239 result.AppendErrorWithFormat ("no custom summary for %s.\n", typeA); 1240 result.SetStatus(eReturnStatusFailed); 1241 return false; 1242 } 1243 1244 } 1245}; 1246 1247OptionDefinition 1248CommandObjectTypeSummaryDelete::CommandOptions::g_option_table[] = 1249{ 1250 { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeBoolean, "Delete from every category."}, 1251 { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Delete from given category."}, 1252 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1253}; 1254 1255class CommandObjectTypeSummaryClear : public CommandObject 1256{ 1257private: 1258 1259 class CommandOptions : public Options 1260 { 1261 public: 1262 1263 CommandOptions (CommandInterpreter &interpreter) : 1264 Options (interpreter) 1265 { 1266 } 1267 1268 virtual 1269 ~CommandOptions (){} 1270 1271 virtual Error 1272 SetOptionValue (uint32_t option_idx, const char *option_arg) 1273 { 1274 Error error; 1275 char short_option = (char) m_getopt_table[option_idx].val; 1276 1277 switch (short_option) 1278 { 1279 case 'a': 1280 m_delete_all = true; 1281 break; 1282 default: 1283 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 1284 break; 1285 } 1286 1287 return error; 1288 } 1289 1290 void 1291 OptionParsingStarting () 1292 { 1293 m_delete_all = false; 1294 } 1295 1296 const OptionDefinition* 1297 GetDefinitions () 1298 { 1299 return g_option_table; 1300 } 1301 1302 // Options table: Required for subclasses of Options. 1303 1304 static OptionDefinition g_option_table[]; 1305 1306 // Instance variables to hold the values for command options. 1307 1308 bool m_delete_all; 1309 bool m_delete_named; 1310 }; 1311 1312 CommandOptions m_options; 1313 1314 virtual Options * 1315 GetOptions () 1316 { 1317 return &m_options; 1318 } 1319 1320 static bool 1321 PerCategoryCallback(void* param, 1322 const char* cate_name, 1323 const FormatCategory::SharedPointer& cate) 1324 { 1325 cate->Summary()->Clear(); 1326 cate->RegexSummary()->Clear(); 1327 return true; 1328 1329 } 1330 1331public: 1332 CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) : 1333 CommandObject (interpreter, 1334 "type summary clear", 1335 "Delete all existing summary styles.", 1336 NULL), m_options(interpreter) 1337 { 1338 } 1339 1340 ~CommandObjectTypeSummaryClear () 1341 { 1342 } 1343 1344 bool 1345 Execute (Args& command, CommandReturnObject &result) 1346 { 1347 1348 if (m_options.m_delete_all) 1349 Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, NULL); 1350 1351 else 1352 { 1353 lldb::FormatCategorySP category; 1354 if (command.GetArgumentCount() > 0) 1355 { 1356 const char* cat_name = command.GetArgumentAtIndex(0); 1357 ConstString cat_nameCS(cat_name); 1358 Debugger::Formatting::Categories::Get(cat_nameCS, category); 1359 } 1360 else 1361 Debugger::Formatting::Categories::Get(ConstString(NULL), category); 1362 category->Clear(); 1363 } 1364 1365 Debugger::Formatting::NamedSummaryFormats::Clear(); 1366 1367 result.SetStatus(eReturnStatusSuccessFinishResult); 1368 return result.Succeeded(); 1369 } 1370 1371}; 1372 1373OptionDefinition 1374CommandObjectTypeSummaryClear::CommandOptions::g_option_table[] = 1375{ 1376 { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeBoolean, "Clear every category."}, 1377 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1378}; 1379 1380//------------------------------------------------------------------------- 1381// CommandObjectTypeSummaryList 1382//------------------------------------------------------------------------- 1383 1384bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, const char* type, const StringSummaryFormat::SharedPointer& entry); 1385bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const StringSummaryFormat::SharedPointer& entry); 1386 1387class CommandObjectTypeSummaryList; 1388 1389struct CommandObjectTypeSummaryList_LoopCallbackParam { 1390 CommandObjectTypeSummaryList* self; 1391 CommandReturnObject* result; 1392 RegularExpression* regex; 1393 RegularExpression* cate_regex; 1394 CommandObjectTypeSummaryList_LoopCallbackParam(CommandObjectTypeSummaryList* S, CommandReturnObject* R, 1395 RegularExpression* X = NULL, 1396 RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {} 1397}; 1398 1399class CommandObjectTypeSummaryList : public CommandObject 1400{ 1401 1402 class CommandOptions : public Options 1403 { 1404 public: 1405 1406 CommandOptions (CommandInterpreter &interpreter) : 1407 Options (interpreter) 1408 { 1409 } 1410 1411 virtual 1412 ~CommandOptions (){} 1413 1414 virtual Error 1415 SetOptionValue (uint32_t option_idx, const char *option_arg) 1416 { 1417 Error error; 1418 char short_option = (char) m_getopt_table[option_idx].val; 1419 1420 switch (short_option) 1421 { 1422 case 'w': 1423 m_category_regex = std::string(option_arg); 1424 break; 1425 default: 1426 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 1427 break; 1428 } 1429 1430 return error; 1431 } 1432 1433 void 1434 OptionParsingStarting () 1435 { 1436 m_category_regex = ""; 1437 } 1438 1439 const OptionDefinition* 1440 GetDefinitions () 1441 { 1442 return g_option_table; 1443 } 1444 1445 // Options table: Required for subclasses of Options. 1446 1447 static OptionDefinition g_option_table[]; 1448 1449 // Instance variables to hold the values for command options. 1450 1451 std::string m_category_regex; 1452 1453 }; 1454 1455 CommandOptions m_options; 1456 1457 virtual Options * 1458 GetOptions () 1459 { 1460 return &m_options; 1461 } 1462 1463public: 1464 CommandObjectTypeSummaryList (CommandInterpreter &interpreter) : 1465 CommandObject (interpreter, 1466 "type summary list", 1467 "Show a list of current summary styles.", 1468 NULL), m_options(interpreter) 1469 { 1470 CommandArgumentEntry type_arg; 1471 CommandArgumentData type_style_arg; 1472 1473 type_style_arg.arg_type = eArgTypeName; 1474 type_style_arg.arg_repetition = eArgRepeatOptional; 1475 1476 type_arg.push_back (type_style_arg); 1477 1478 m_arguments.push_back (type_arg); 1479 } 1480 1481 ~CommandObjectTypeSummaryList () 1482 { 1483 } 1484 1485 bool 1486 Execute (Args& command, CommandReturnObject &result) 1487 { 1488 const size_t argc = command.GetArgumentCount(); 1489 1490 CommandObjectTypeSummaryList_LoopCallbackParam *param; 1491 RegularExpression* cate_regex = 1492 m_options.m_category_regex.empty() ? NULL : 1493 new RegularExpression(m_options.m_category_regex.c_str()); 1494 1495 if (argc == 1) { 1496 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 1497 regex->Compile(command.GetArgumentAtIndex(0)); 1498 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex,cate_regex); 1499 } 1500 else 1501 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,NULL,cate_regex); 1502 1503 Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback,param); 1504 1505 if (Debugger::Formatting::NamedSummaryFormats::GetCount() > 0) 1506 { 1507 result.GetOutputStream().Printf("Named summaries:\n"); 1508 if (argc == 1) { 1509 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 1510 regex->Compile(command.GetArgumentAtIndex(0)); 1511 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex); 1512 } 1513 else 1514 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result); 1515 Debugger::Formatting::NamedSummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param); 1516 delete param; 1517 } 1518 1519 if (cate_regex) 1520 delete cate_regex; 1521 1522 result.SetStatus(eReturnStatusSuccessFinishResult); 1523 return result.Succeeded(); 1524 } 1525 1526private: 1527 1528 static bool 1529 PerCategoryCallback(void* param_vp, 1530 const char* cate_name, 1531 const FormatCategory::SharedPointer& cate) 1532 { 1533 1534 CommandObjectTypeSummaryList_LoopCallbackParam* param = 1535 (CommandObjectTypeSummaryList_LoopCallbackParam*)param_vp; 1536 CommandReturnObject* result = param->result; 1537 1538 // if the category is disabled or empty and there is no regex, just skip it 1539 if ((cate->IsEnabled() == false || cate->GetCount() == 0) && param->cate_regex == NULL) 1540 return true; 1541 1542 // if we have a regex and this category does not match it, just skip it 1543 if(param->cate_regex != NULL && param->cate_regex->Execute(cate_name) == false) 1544 return true; 1545 1546 result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n", 1547 cate_name, 1548 (cate->IsEnabled() ? "enabled" : "disabled")); 1549 1550 cate->Summary()->LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param_vp); 1551 1552 if (cate->RegexSummary()->GetCount() > 0) 1553 { 1554 result->GetOutputStream().Printf("Regex-based summaries (slower):\n"); 1555 cate->RegexSummary()->LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, param_vp); 1556 } 1557 return true; 1558 } 1559 1560 bool 1561 LoopCallback (const char* type, 1562 const SummaryFormat::SharedPointer& entry, 1563 RegularExpression* regex, 1564 CommandReturnObject *result) 1565 { 1566 if (regex == NULL || regex->Execute(type)) 1567 result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); 1568 return true; 1569 } 1570 1571 friend bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, const char* type, const SummaryFormat::SharedPointer& entry); 1572 friend bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SummaryFormat::SharedPointer& entry); 1573}; 1574 1575bool 1576CommandObjectTypeSummaryList_LoopCallback ( 1577 void* pt2self, 1578 const char* type, 1579 const SummaryFormat::SharedPointer& entry) 1580{ 1581 CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self; 1582 return param->self->LoopCallback(type, entry, param->regex, param->result); 1583} 1584 1585bool 1586CommandObjectTypeRXSummaryList_LoopCallback ( 1587 void* pt2self, 1588 lldb::RegularExpressionSP regex, 1589 const SummaryFormat::SharedPointer& entry) 1590{ 1591 CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self; 1592 return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); 1593} 1594 1595OptionDefinition 1596CommandObjectTypeSummaryList::CommandOptions::g_option_table[] = 1597{ 1598 { LLDB_OPT_SET_ALL, false, "category-regex", 'w', required_argument, NULL, 0, eArgTypeName, "Only show categories matching this filter."}, 1599 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1600}; 1601 1602//------------------------------------------------------------------------- 1603// CommandObjectTypeCategoryEnable 1604//------------------------------------------------------------------------- 1605 1606class CommandObjectTypeCategoryEnable : public CommandObject 1607{ 1608public: 1609 CommandObjectTypeCategoryEnable (CommandInterpreter &interpreter) : 1610 CommandObject (interpreter, 1611 "type category enable", 1612 "Enable a category as a source of summaries.", 1613 NULL) 1614 { 1615 CommandArgumentEntry type_arg; 1616 CommandArgumentData type_style_arg; 1617 1618 type_style_arg.arg_type = eArgTypeName; 1619 type_style_arg.arg_repetition = eArgRepeatPlus; 1620 1621 type_arg.push_back (type_style_arg); 1622 1623 m_arguments.push_back (type_arg); 1624 1625 } 1626 1627 ~CommandObjectTypeCategoryEnable () 1628 { 1629 } 1630 1631 bool 1632 Execute (Args& command, CommandReturnObject &result) 1633 { 1634 const size_t argc = command.GetArgumentCount(); 1635 1636 if (argc < 1) 1637 { 1638 result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str()); 1639 result.SetStatus(eReturnStatusFailed); 1640 return false; 1641 } 1642 1643 for (int i = argc - 1; i >= 0; i--) 1644 { 1645 const char* typeA = command.GetArgumentAtIndex(i); 1646 ConstString typeCS(typeA); 1647 1648 if (!typeCS) 1649 { 1650 result.AppendError("empty category name not allowed"); 1651 result.SetStatus(eReturnStatusFailed); 1652 return false; 1653 } 1654 Debugger::Formatting::Categories::Enable(typeCS); 1655 } 1656 1657 result.SetStatus(eReturnStatusSuccessFinishResult); 1658 return result.Succeeded(); 1659 } 1660 1661}; 1662 1663//------------------------------------------------------------------------- 1664// CommandObjectTypeCategoryDelete 1665//------------------------------------------------------------------------- 1666 1667class CommandObjectTypeCategoryDelete : public CommandObject 1668{ 1669public: 1670 CommandObjectTypeCategoryDelete (CommandInterpreter &interpreter) : 1671 CommandObject (interpreter, 1672 "type category delete", 1673 "Delete a category and all associated summaries.", 1674 NULL) 1675 { 1676 CommandArgumentEntry type_arg; 1677 CommandArgumentData type_style_arg; 1678 1679 type_style_arg.arg_type = eArgTypeName; 1680 type_style_arg.arg_repetition = eArgRepeatPlus; 1681 1682 type_arg.push_back (type_style_arg); 1683 1684 m_arguments.push_back (type_arg); 1685 1686 } 1687 1688 ~CommandObjectTypeCategoryDelete () 1689 { 1690 } 1691 1692 bool 1693 Execute (Args& command, CommandReturnObject &result) 1694 { 1695 const size_t argc = command.GetArgumentCount(); 1696 1697 if (argc < 1) 1698 { 1699 result.AppendErrorWithFormat ("%s takes 1 or more arg.\n", m_cmd_name.c_str()); 1700 result.SetStatus(eReturnStatusFailed); 1701 return false; 1702 } 1703 1704 bool success = true; 1705 1706 // the order is not relevant here 1707 for (int i = argc - 1; i >= 0; i--) 1708 { 1709 const char* typeA = command.GetArgumentAtIndex(i); 1710 ConstString typeCS(typeA); 1711 1712 if (!typeCS) 1713 { 1714 result.AppendError("empty category name not allowed"); 1715 result.SetStatus(eReturnStatusFailed); 1716 return false; 1717 } 1718 if (!Debugger::Formatting::Categories::Delete(typeCS)) 1719 success = false; // keep deleting even if we hit an error 1720 } 1721 if (success) 1722 { 1723 result.SetStatus(eReturnStatusSuccessFinishResult); 1724 return result.Succeeded(); 1725 } 1726 else 1727 { 1728 result.AppendError("cannot delete one or more categories\n"); 1729 result.SetStatus(eReturnStatusFailed); 1730 return false; 1731 } 1732 } 1733}; 1734 1735//------------------------------------------------------------------------- 1736// CommandObjectTypeCategoryDisable 1737//------------------------------------------------------------------------- 1738 1739class CommandObjectTypeCategoryDisable : public CommandObject 1740{ 1741public: 1742 CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) : 1743 CommandObject (interpreter, 1744 "type category disable", 1745 "Disable a category as a source of summaries.", 1746 NULL) 1747 { 1748 CommandArgumentEntry type_arg; 1749 CommandArgumentData type_style_arg; 1750 1751 type_style_arg.arg_type = eArgTypeName; 1752 type_style_arg.arg_repetition = eArgRepeatPlus; 1753 1754 type_arg.push_back (type_style_arg); 1755 1756 m_arguments.push_back (type_arg); 1757 1758 } 1759 1760 ~CommandObjectTypeCategoryDisable () 1761 { 1762 } 1763 1764 bool 1765 Execute (Args& command, CommandReturnObject &result) 1766 { 1767 const size_t argc = command.GetArgumentCount(); 1768 1769 if (argc < 1) 1770 { 1771 result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str()); 1772 result.SetStatus(eReturnStatusFailed); 1773 return false; 1774 } 1775 1776 // the order is not relevant here 1777 for (int i = argc - 1; i >= 0; i--) 1778 { 1779 const char* typeA = command.GetArgumentAtIndex(i); 1780 ConstString typeCS(typeA); 1781 1782 if (!typeCS) 1783 { 1784 result.AppendError("empty category name not allowed"); 1785 result.SetStatus(eReturnStatusFailed); 1786 return false; 1787 } 1788 Debugger::Formatting::Categories::Disable(typeCS); 1789 } 1790 1791 result.SetStatus(eReturnStatusSuccessFinishResult); 1792 return result.Succeeded(); 1793 } 1794 1795}; 1796 1797//------------------------------------------------------------------------- 1798// CommandObjectTypeCategoryList 1799//------------------------------------------------------------------------- 1800 1801class CommandObjectTypeCategoryList : public CommandObject 1802{ 1803private: 1804 1805 struct CommandObjectTypeCategoryList_CallbackParam 1806 { 1807 CommandReturnObject* result; 1808 RegularExpression* regex; 1809 1810 CommandObjectTypeCategoryList_CallbackParam(CommandReturnObject* res, 1811 RegularExpression* rex = NULL) : 1812 result(res), 1813 regex(rex) 1814 { 1815 } 1816 1817 }; 1818 1819 static bool 1820 PerCategoryCallback(void* param_vp, 1821 const char* cate_name, 1822 const FormatCategory::SharedPointer& cate) 1823 { 1824 CommandObjectTypeCategoryList_CallbackParam* param = 1825 (CommandObjectTypeCategoryList_CallbackParam*)param_vp; 1826 CommandReturnObject* result = param->result; 1827 RegularExpression* regex = param->regex; 1828 1829 if (regex == NULL || regex->Execute(cate_name)) 1830 result->GetOutputStream().Printf("Category %s is%s enabled\n", 1831 cate_name, 1832 (cate->IsEnabled() ? "" : " not")); 1833 return true; 1834 } 1835public: 1836 CommandObjectTypeCategoryList (CommandInterpreter &interpreter) : 1837 CommandObject (interpreter, 1838 "type category list", 1839 "Provide a list of all existing categories.", 1840 NULL) 1841 { 1842 CommandArgumentEntry type_arg; 1843 CommandArgumentData type_style_arg; 1844 1845 type_style_arg.arg_type = eArgTypeName; 1846 type_style_arg.arg_repetition = eArgRepeatOptional; 1847 1848 type_arg.push_back (type_style_arg); 1849 1850 m_arguments.push_back (type_arg); 1851 } 1852 1853 ~CommandObjectTypeCategoryList () 1854 { 1855 } 1856 1857 bool 1858 Execute (Args& command, CommandReturnObject &result) 1859 { 1860 const size_t argc = command.GetArgumentCount(); 1861 RegularExpression* regex = NULL; 1862 1863 if (argc == 0) 1864 ; 1865 else if (argc == 1) 1866 regex = new RegularExpression(command.GetArgumentAtIndex(0)); 1867 else 1868 { 1869 result.AppendErrorWithFormat ("%s takes 0 or one arg.\n", m_cmd_name.c_str()); 1870 result.SetStatus(eReturnStatusFailed); 1871 return false; 1872 } 1873 1874 CommandObjectTypeCategoryList_CallbackParam param(&result, 1875 regex); 1876 1877 Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, ¶m); 1878 1879 if (regex) 1880 delete regex; 1881 1882 result.SetStatus(eReturnStatusSuccessFinishResult); 1883 return result.Succeeded(); 1884 } 1885 1886}; 1887 1888class CommandObjectTypeFormat : public CommandObjectMultiword 1889{ 1890public: 1891 CommandObjectTypeFormat (CommandInterpreter &interpreter) : 1892 CommandObjectMultiword (interpreter, 1893 "type format", 1894 "A set of commands for editing variable value display options", 1895 "type format [<sub-command-options>] ") 1896 { 1897 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter))); 1898 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFormatClear (interpreter))); 1899 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter))); 1900 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFormatList (interpreter))); 1901 } 1902 1903 1904 ~CommandObjectTypeFormat () 1905 { 1906 } 1907}; 1908 1909class CommandObjectTypeCategory : public CommandObjectMultiword 1910{ 1911public: 1912 CommandObjectTypeCategory (CommandInterpreter &interpreter) : 1913 CommandObjectMultiword (interpreter, 1914 "type category", 1915 "A set of commands for operating on categories", 1916 "type category [<sub-command-options>] ") 1917 { 1918 LoadSubCommand ("enable", CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter))); 1919 LoadSubCommand ("disable", CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter))); 1920 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter))); 1921 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeCategoryList (interpreter))); 1922 } 1923 1924 1925 ~CommandObjectTypeCategory () 1926 { 1927 } 1928}; 1929 1930class CommandObjectTypeSummary : public CommandObjectMultiword 1931{ 1932public: 1933 CommandObjectTypeSummary (CommandInterpreter &interpreter) : 1934 CommandObjectMultiword (interpreter, 1935 "type summary", 1936 "A set of commands for editing variable summary display options", 1937 "type summary [<sub-command-options>] ") 1938 { 1939 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter))); 1940 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter))); 1941 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter))); 1942 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); 1943 } 1944 1945 1946 ~CommandObjectTypeSummary () 1947 { 1948 } 1949}; 1950 1951//------------------------------------------------------------------------- 1952// CommandObjectType 1953//------------------------------------------------------------------------- 1954 1955CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) : 1956 CommandObjectMultiword (interpreter, 1957 "type", 1958 "A set of commands for operating on the type system", 1959 "type [<sub-command-options>]") 1960{ 1961 LoadSubCommand ("category", CommandObjectSP (new CommandObjectTypeCategory (interpreter))); 1962 LoadSubCommand ("format", CommandObjectSP (new CommandObjectTypeFormat (interpreter))); 1963 LoadSubCommand ("summary", CommandObjectSP (new CommandObjectTypeSummary (interpreter))); 1964} 1965 1966 1967CommandObjectType::~CommandObjectType () 1968{ 1969} 1970 1971 1972