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