CommandObjectType.cpp revision 2bc9eb3ba78efc64a273729b480bafc3bbaa433a
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 CommandObjectTypeSummaryList_LoopCallbackParam(CommandObjectTypeSummaryList* S, CommandReturnObject* R, 1394 RegularExpression* X = NULL) : self(S), result(R), regex(X) {} 1395}; 1396 1397class CommandObjectTypeSummaryList : public CommandObject 1398{ 1399public: 1400 CommandObjectTypeSummaryList (CommandInterpreter &interpreter) : 1401 CommandObject (interpreter, 1402 "type summary list", 1403 "Show a list of current summary styles.", 1404 NULL) 1405 { 1406 CommandArgumentEntry type_arg; 1407 CommandArgumentData type_style_arg; 1408 1409 type_style_arg.arg_type = eArgTypeName; 1410 type_style_arg.arg_repetition = eArgRepeatOptional; 1411 1412 type_arg.push_back (type_style_arg); 1413 1414 m_arguments.push_back (type_arg); 1415 } 1416 1417 ~CommandObjectTypeSummaryList () 1418 { 1419 } 1420 1421 bool 1422 Execute (Args& command, CommandReturnObject &result) 1423 { 1424 const size_t argc = command.GetArgumentCount(); 1425 1426 CommandObjectTypeSummaryList_LoopCallbackParam *param; 1427 1428 if (argc == 1) { 1429 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 1430 regex->Compile(command.GetArgumentAtIndex(0)); 1431 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex); 1432 } 1433 else 1434 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result); 1435 1436 Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback,param); 1437 1438 if (Debugger::Formatting::NamedSummaryFormats::GetCount() > 0) 1439 { 1440 result.GetOutputStream().Printf("Named summaries:\n"); 1441 if (argc == 1) { 1442 RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); 1443 regex->Compile(command.GetArgumentAtIndex(0)); 1444 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex); 1445 } 1446 else 1447 param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result); 1448 Debugger::Formatting::NamedSummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param); 1449 delete param; 1450 } 1451 1452 result.SetStatus(eReturnStatusSuccessFinishResult); 1453 return result.Succeeded(); 1454 } 1455 1456private: 1457 1458 static bool 1459 PerCategoryCallback(void* param, 1460 const char* cate_name, 1461 const FormatCategory::SharedPointer& cate) 1462 { 1463 1464 CommandReturnObject* result = ((CommandObjectTypeSummaryList_LoopCallbackParam*)param)->result; 1465 1466 result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n", 1467 cate_name, 1468 (cate->IsEnabled() ? "enabled" : "disabled")); 1469 1470 cate->Summary()->LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param); 1471 1472 if (cate->RegexSummary()->GetCount() > 0) 1473 { 1474 result->GetOutputStream().Printf("Regex-based summaries (slower):\n"); 1475 cate->RegexSummary()->LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, param); 1476 } 1477 return true; 1478 } 1479 1480 bool 1481 LoopCallback (const char* type, 1482 const SummaryFormat::SharedPointer& entry, 1483 RegularExpression* regex, 1484 CommandReturnObject *result) 1485 { 1486 if (regex == NULL || regex->Execute(type)) 1487 result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); 1488 return true; 1489 } 1490 1491 friend bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, const char* type, const SummaryFormat::SharedPointer& entry); 1492 friend bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SummaryFormat::SharedPointer& entry); 1493}; 1494 1495bool 1496CommandObjectTypeSummaryList_LoopCallback ( 1497 void* pt2self, 1498 const char* type, 1499 const SummaryFormat::SharedPointer& entry) 1500{ 1501 CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self; 1502 return param->self->LoopCallback(type, entry, param->regex, param->result); 1503} 1504 1505bool 1506CommandObjectTypeRXSummaryList_LoopCallback ( 1507 void* pt2self, 1508 lldb::RegularExpressionSP regex, 1509 const SummaryFormat::SharedPointer& entry) 1510{ 1511 CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self; 1512 return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); 1513} 1514 1515//------------------------------------------------------------------------- 1516// CommandObjectTypeCategoryEnable 1517//------------------------------------------------------------------------- 1518 1519class CommandObjectTypeCategoryEnable : public CommandObject 1520{ 1521public: 1522 CommandObjectTypeCategoryEnable (CommandInterpreter &interpreter) : 1523 CommandObject (interpreter, 1524 "type category enable", 1525 "Enable a category as a source of summaries.", 1526 NULL) 1527 { 1528 CommandArgumentEntry type_arg; 1529 CommandArgumentData type_style_arg; 1530 1531 type_style_arg.arg_type = eArgTypeName; 1532 type_style_arg.arg_repetition = eArgRepeatPlus; 1533 1534 type_arg.push_back (type_style_arg); 1535 1536 m_arguments.push_back (type_arg); 1537 1538 } 1539 1540 ~CommandObjectTypeCategoryEnable () 1541 { 1542 } 1543 1544 bool 1545 Execute (Args& command, CommandReturnObject &result) 1546 { 1547 const size_t argc = command.GetArgumentCount(); 1548 1549 if (argc < 1) 1550 { 1551 result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str()); 1552 result.SetStatus(eReturnStatusFailed); 1553 return false; 1554 } 1555 1556 for (int i = argc - 1; i >= 0; i--) 1557 { 1558 const char* typeA = command.GetArgumentAtIndex(i); 1559 ConstString typeCS(typeA); 1560 1561 if (!typeCS) 1562 { 1563 result.AppendError("empty category name not allowed"); 1564 result.SetStatus(eReturnStatusFailed); 1565 return false; 1566 } 1567 Debugger::Formatting::Categories::Enable(typeCS); 1568 } 1569 1570 result.SetStatus(eReturnStatusSuccessFinishResult); 1571 return result.Succeeded(); 1572 } 1573 1574}; 1575 1576//------------------------------------------------------------------------- 1577// CommandObjectTypeCategoryDelete 1578//------------------------------------------------------------------------- 1579 1580class CommandObjectTypeCategoryDelete : public CommandObject 1581{ 1582public: 1583 CommandObjectTypeCategoryDelete (CommandInterpreter &interpreter) : 1584 CommandObject (interpreter, 1585 "type category delete", 1586 "Delete a category and all associated summaries.", 1587 NULL) 1588 { 1589 CommandArgumentEntry type_arg; 1590 CommandArgumentData type_style_arg; 1591 1592 type_style_arg.arg_type = eArgTypeName; 1593 type_style_arg.arg_repetition = eArgRepeatPlus; 1594 1595 type_arg.push_back (type_style_arg); 1596 1597 m_arguments.push_back (type_arg); 1598 1599 } 1600 1601 ~CommandObjectTypeCategoryDelete () 1602 { 1603 } 1604 1605 bool 1606 Execute (Args& command, CommandReturnObject &result) 1607 { 1608 const size_t argc = command.GetArgumentCount(); 1609 1610 if (argc < 1) 1611 { 1612 result.AppendErrorWithFormat ("%s takes 1 or more arg.\n", m_cmd_name.c_str()); 1613 result.SetStatus(eReturnStatusFailed); 1614 return false; 1615 } 1616 1617 bool success = true; 1618 1619 // the order is not relevant here 1620 for (int i = argc - 1; i >= 0; i--) 1621 { 1622 const char* typeA = command.GetArgumentAtIndex(i); 1623 ConstString typeCS(typeA); 1624 1625 if (!typeCS) 1626 { 1627 result.AppendError("empty category name not allowed"); 1628 result.SetStatus(eReturnStatusFailed); 1629 return false; 1630 } 1631 if (!Debugger::Formatting::Categories::Delete(typeCS)) 1632 success = false; // keep deleting even if we hit an error 1633 } 1634 if (success) 1635 { 1636 result.SetStatus(eReturnStatusSuccessFinishResult); 1637 return result.Succeeded(); 1638 } 1639 else 1640 { 1641 result.AppendError("cannot delete one or more categories\n"); 1642 result.SetStatus(eReturnStatusFailed); 1643 return false; 1644 } 1645 } 1646}; 1647 1648//------------------------------------------------------------------------- 1649// CommandObjectTypeCategoryDisable 1650//------------------------------------------------------------------------- 1651 1652class CommandObjectTypeCategoryDisable : public CommandObject 1653{ 1654public: 1655 CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) : 1656 CommandObject (interpreter, 1657 "type category disable", 1658 "Disable a category as a source of summaries.", 1659 NULL) 1660 { 1661 CommandArgumentEntry type_arg; 1662 CommandArgumentData type_style_arg; 1663 1664 type_style_arg.arg_type = eArgTypeName; 1665 type_style_arg.arg_repetition = eArgRepeatPlus; 1666 1667 type_arg.push_back (type_style_arg); 1668 1669 m_arguments.push_back (type_arg); 1670 1671 } 1672 1673 ~CommandObjectTypeCategoryDisable () 1674 { 1675 } 1676 1677 bool 1678 Execute (Args& command, CommandReturnObject &result) 1679 { 1680 const size_t argc = command.GetArgumentCount(); 1681 1682 if (argc < 1) 1683 { 1684 result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str()); 1685 result.SetStatus(eReturnStatusFailed); 1686 return false; 1687 } 1688 1689 // the order is not relevant here 1690 for (int i = argc - 1; i >= 0; i--) 1691 { 1692 const char* typeA = command.GetArgumentAtIndex(i); 1693 ConstString typeCS(typeA); 1694 1695 if (!typeCS) 1696 { 1697 result.AppendError("empty category name not allowed"); 1698 result.SetStatus(eReturnStatusFailed); 1699 return false; 1700 } 1701 Debugger::Formatting::Categories::Disable(typeCS); 1702 } 1703 1704 result.SetStatus(eReturnStatusSuccessFinishResult); 1705 return result.Succeeded(); 1706 } 1707 1708}; 1709 1710//------------------------------------------------------------------------- 1711// CommandObjectTypeCategoryList 1712//------------------------------------------------------------------------- 1713 1714class CommandObjectTypeCategoryList : public CommandObject 1715{ 1716private: 1717 static bool 1718 PerCategoryCallback(void* param, 1719 const char* cate_name, 1720 const FormatCategory::SharedPointer& cate) 1721 { 1722 CommandReturnObject* result = (CommandReturnObject*)param; 1723 result->GetOutputStream().Printf("Category %s is%s enabled\n", 1724 cate_name, 1725 (cate->IsEnabled() ? "" : " not")); 1726 return true; 1727 } 1728public: 1729 CommandObjectTypeCategoryList (CommandInterpreter &interpreter) : 1730 CommandObject (interpreter, 1731 "type category list", 1732 "Provide a list of all existing categories.", 1733 NULL) 1734 { 1735 } 1736 1737 ~CommandObjectTypeCategoryList () 1738 { 1739 } 1740 1741 bool 1742 Execute (Args& command, CommandReturnObject &result) 1743 { 1744 Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, (void*)&result); 1745 result.SetStatus(eReturnStatusSuccessFinishResult); 1746 return result.Succeeded(); 1747 } 1748 1749}; 1750 1751class CommandObjectTypeFormat : public CommandObjectMultiword 1752{ 1753public: 1754 CommandObjectTypeFormat (CommandInterpreter &interpreter) : 1755 CommandObjectMultiword (interpreter, 1756 "type format", 1757 "A set of commands for editing variable value display options", 1758 "type format [<sub-command-options>] ") 1759 { 1760 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter))); 1761 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFormatClear (interpreter))); 1762 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter))); 1763 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFormatList (interpreter))); 1764 } 1765 1766 1767 ~CommandObjectTypeFormat () 1768 { 1769 } 1770}; 1771 1772class CommandObjectTypeCategory : public CommandObjectMultiword 1773{ 1774public: 1775 CommandObjectTypeCategory (CommandInterpreter &interpreter) : 1776 CommandObjectMultiword (interpreter, 1777 "type category", 1778 "A set of commands for operating on categories", 1779 "type category [<sub-command-options>] ") 1780 { 1781 LoadSubCommand ("enable", CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter))); 1782 LoadSubCommand ("disable", CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter))); 1783 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter))); 1784 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeCategoryList (interpreter))); 1785 } 1786 1787 1788 ~CommandObjectTypeCategory () 1789 { 1790 } 1791}; 1792 1793class CommandObjectTypeSummary : public CommandObjectMultiword 1794{ 1795public: 1796 CommandObjectTypeSummary (CommandInterpreter &interpreter) : 1797 CommandObjectMultiword (interpreter, 1798 "type summary", 1799 "A set of commands for editing variable summary display options", 1800 "type summary [<sub-command-options>] ") 1801 { 1802 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter))); 1803 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter))); 1804 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter))); 1805 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); 1806 } 1807 1808 1809 ~CommandObjectTypeSummary () 1810 { 1811 } 1812}; 1813 1814//------------------------------------------------------------------------- 1815// CommandObjectType 1816//------------------------------------------------------------------------- 1817 1818CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) : 1819 CommandObjectMultiword (interpreter, 1820 "type", 1821 "A set of commands for operating on the type system", 1822 "type [<sub-command-options>]") 1823{ 1824 LoadSubCommand ("category", CommandObjectSP (new CommandObjectTypeCategory (interpreter))); 1825 LoadSubCommand ("format", CommandObjectSP (new CommandObjectTypeFormat (interpreter))); 1826 LoadSubCommand ("summary", CommandObjectSP (new CommandObjectTypeSummary (interpreter))); 1827} 1828 1829 1830CommandObjectType::~CommandObjectType () 1831{ 1832} 1833 1834 1835