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 = ConstString(option_arg).GetCString(); 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 = NULL; 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 const char* category_name, 1040 Error* error) 1041 { 1042 lldb::FormatCategorySP category; 1043 Debugger::Formatting::Categories::Get(ConstString(category_name), 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 = ConstString(option_arg).GetCString(); 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 = NULL; 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 const char* 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), 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 // CommandObjectTypeSynthList 1892 //------------------------------------------------------------------------- 1893 1894 bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, const char* type, const SyntheticFilter::SharedPointer& entry); 1895 bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticFilter::SharedPointer& entry); 1896 1897 class CommandObjectTypeSynthList; 1898 1899 struct CommandObjectTypeSynthList_LoopCallbackParam { 1900 CommandObjectTypeSynthList* self; 1901 CommandReturnObject* result; 1902 RegularExpression* regex; 1903 RegularExpression* cate_regex; 1904 CommandObjectTypeSynthList_LoopCallbackParam(CommandObjectTypeSynthList* S, CommandReturnObject* R, 1905 RegularExpression* X = NULL, 1906 RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {} 1907 }; 1908 1909 class CommandObjectTypeSynthList : 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 CommandObjectTypeSynthList (CommandInterpreter &interpreter) : 1975 CommandObject (interpreter, 1976 "type synthetic list", 1977 "Show a list of current synthetic providers.", 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 ~CommandObjectTypeSynthList () 1992 { 1993 } 1994 1995 bool 1996 Execute (Args& command, CommandReturnObject &result) 1997 { 1998 const size_t argc = command.GetArgumentCount(); 1999 2000 CommandObjectTypeSynthList_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 CommandObjectTypeSynthList_LoopCallbackParam(this,&result,regex,cate_regex); 2009 } 2010 else 2011 param = new CommandObjectTypeSynthList_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 CommandObjectTypeSynthList_LoopCallbackParam* param = 2031 (CommandObjectTypeSynthList_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(CommandObjectTypeSynthList_LoopCallback, param_vp); 2047 2048 if (cate->RegexFilter()->GetCount() > 0) 2049 { 2050 result->GetOutputStream().Printf("Regex-based filters (slower):\n"); 2051 cate->RegexFilter()->LoopThrough(CommandObjectTypeSynthRXList_LoopCallback, param_vp); 2052 } 2053 2054 return true; 2055 } 2056 2057 bool 2058 LoopCallback (const char* type, 2059 const SyntheticFilter::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 CommandObjectTypeSynthList_LoopCallback(void* pt2self, const char* type, const SyntheticFilter::SharedPointer& entry); 2069 friend bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticFilter::SharedPointer& entry); 2070 }; 2071 2072 bool 2073 CommandObjectTypeSynthList_LoopCallback (void* pt2self, 2074 const char* type, 2075 const SyntheticFilter::SharedPointer& entry) 2076 { 2077 CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self; 2078 return param->self->LoopCallback(type, entry, param->regex, param->result); 2079 } 2080 2081 bool 2082 CommandObjectTypeSynthRXList_LoopCallback (void* pt2self, 2083 lldb::RegularExpressionSP regex, 2084 const SyntheticFilter::SharedPointer& entry) 2085 { 2086 CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self; 2087 return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); 2088 } 2089 2090 2091 OptionDefinition 2092 CommandObjectTypeSynthList::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 // CommandObjectTypeSynthDelete 2100 //------------------------------------------------------------------------- 2101 2102 class CommandObjectTypeSynthDelete : public CommandObject 2103 { 2104 private: 2105 class CommandOptions : public Options 2106 { 2107 public: 2108 2109 CommandOptions (CommandInterpreter &interpreter) : 2110 Options (interpreter) 2111 { 2112 } 2113 2114 virtual 2115 ~CommandOptions (){} 2116 2117 virtual Error 2118 SetOptionValue (uint32_t option_idx, const char *option_arg) 2119 { 2120 Error error; 2121 char short_option = (char) m_getopt_table[option_idx].val; 2122 2123 switch (short_option) 2124 { 2125 case 'a': 2126 m_delete_all = true; 2127 break; 2128 case 'w': 2129 m_category = ConstString(option_arg).GetCString(); 2130 break; 2131 default: 2132 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 2133 break; 2134 } 2135 2136 return error; 2137 } 2138 2139 void 2140 OptionParsingStarting () 2141 { 2142 m_delete_all = false; 2143 m_category = NULL; 2144 } 2145 2146 const OptionDefinition* 2147 GetDefinitions () 2148 { 2149 return g_option_table; 2150 } 2151 2152 // Options table: Required for subclasses of Options. 2153 2154 static OptionDefinition g_option_table[]; 2155 2156 // Instance variables to hold the values for command options. 2157 2158 bool m_delete_all; 2159 const char* m_category; 2160 2161 }; 2162 2163 CommandOptions m_options; 2164 2165 virtual Options * 2166 GetOptions () 2167 { 2168 return &m_options; 2169 } 2170 2171 static bool 2172 PerCategoryCallback(void* param, 2173 const char* cate_name, 2174 const FormatCategory::SharedPointer& cate) 2175 { 2176 const char* name = (const char*)param; 2177 return cate->Delete(name, FormatCategory::eFilter | FormatCategory::eRegexFilter); 2178 } 2179 2180 public: 2181 CommandObjectTypeSynthDelete (CommandInterpreter &interpreter) : 2182 CommandObject (interpreter, 2183 "type synthetic delete", 2184 "Delete an existing synthetic provider for a type.", 2185 NULL), m_options(interpreter) 2186 { 2187 CommandArgumentEntry type_arg; 2188 CommandArgumentData type_style_arg; 2189 2190 type_style_arg.arg_type = eArgTypeName; 2191 type_style_arg.arg_repetition = eArgRepeatPlain; 2192 2193 type_arg.push_back (type_style_arg); 2194 2195 m_arguments.push_back (type_arg); 2196 2197 } 2198 2199 ~CommandObjectTypeSynthDelete () 2200 { 2201 } 2202 2203 bool 2204 Execute (Args& command, CommandReturnObject &result) 2205 { 2206 const size_t argc = command.GetArgumentCount(); 2207 2208 if (argc != 1) 2209 { 2210 result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); 2211 result.SetStatus(eReturnStatusFailed); 2212 return false; 2213 } 2214 2215 const char* typeA = command.GetArgumentAtIndex(0); 2216 ConstString typeCS(typeA); 2217 2218 if (!typeCS) 2219 { 2220 result.AppendError("empty typenames not allowed"); 2221 result.SetStatus(eReturnStatusFailed); 2222 return false; 2223 } 2224 2225 if (m_options.m_delete_all) 2226 { 2227 Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, (void*)typeCS.GetCString()); 2228 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2229 return result.Succeeded(); 2230 } 2231 2232 lldb::FormatCategorySP category; 2233 Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category); 2234 2235 bool delete_category = category->Filter()->Delete(typeCS.GetCString()); 2236 delete_category = category->RegexFilter()->Delete(typeCS.GetCString()) || delete_category; 2237 2238 if (delete_category) 2239 { 2240 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2241 return result.Succeeded(); 2242 } 2243 else 2244 { 2245 result.AppendErrorWithFormat ("no custom synthetic provider for %s.\n", typeA); 2246 result.SetStatus(eReturnStatusFailed); 2247 return false; 2248 } 2249 2250 } 2251 }; 2252 2253 OptionDefinition 2254 CommandObjectTypeSynthDelete::CommandOptions::g_option_table[] = 2255 { 2256 { LLDB_OPT_SET_1, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Delete from every category."}, 2257 { LLDB_OPT_SET_2, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Delete from given category."}, 2258 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 2259 }; 2260 2261 //------------------------------------------------------------------------- 2262 // CommandObjectTypeSynthClear 2263 //------------------------------------------------------------------------- 2264 2265 class CommandObjectTypeSynthClear : public CommandObject 2266 { 2267 private: 2268 2269 class CommandOptions : public Options 2270 { 2271 public: 2272 2273 CommandOptions (CommandInterpreter &interpreter) : 2274 Options (interpreter) 2275 { 2276 } 2277 2278 virtual 2279 ~CommandOptions (){} 2280 2281 virtual Error 2282 SetOptionValue (uint32_t option_idx, const char *option_arg) 2283 { 2284 Error error; 2285 char short_option = (char) m_getopt_table[option_idx].val; 2286 2287 switch (short_option) 2288 { 2289 case 'a': 2290 m_delete_all = true; 2291 break; 2292 default: 2293 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 2294 break; 2295 } 2296 2297 return error; 2298 } 2299 2300 void 2301 OptionParsingStarting () 2302 { 2303 m_delete_all = false; 2304 } 2305 2306 const OptionDefinition* 2307 GetDefinitions () 2308 { 2309 return g_option_table; 2310 } 2311 2312 // Options table: Required for subclasses of Options. 2313 2314 static OptionDefinition g_option_table[]; 2315 2316 // Instance variables to hold the values for command options. 2317 2318 bool m_delete_all; 2319 bool m_delete_named; 2320 }; 2321 2322 CommandOptions m_options; 2323 2324 virtual Options * 2325 GetOptions () 2326 { 2327 return &m_options; 2328 } 2329 2330 static bool 2331 PerCategoryCallback(void* param, 2332 const char* cate_name, 2333 const FormatCategory::SharedPointer& cate) 2334 { 2335 cate->Clear(FormatCategory::eFilter | FormatCategory::eRegexFilter); 2336 return true; 2337 2338 } 2339 2340 public: 2341 CommandObjectTypeSynthClear (CommandInterpreter &interpreter) : 2342 CommandObject (interpreter, 2343 "type synthetic clear", 2344 "Delete all existing synthetic providers.", 2345 NULL), m_options(interpreter) 2346 { 2347 } 2348 2349 ~CommandObjectTypeSynthClear () 2350 { 2351 } 2352 2353 bool 2354 Execute (Args& command, CommandReturnObject &result) 2355 { 2356 2357 if (m_options.m_delete_all) 2358 Debugger::Formatting::Categories::LoopThrough(PerCategoryCallback, NULL); 2359 2360 else 2361 { 2362 lldb::FormatCategorySP category; 2363 if (command.GetArgumentCount() > 0) 2364 { 2365 const char* cat_name = command.GetArgumentAtIndex(0); 2366 ConstString cat_nameCS(cat_name); 2367 Debugger::Formatting::Categories::Get(cat_nameCS, category); 2368 } 2369 else 2370 Debugger::Formatting::Categories::Get(ConstString(NULL), category); 2371 category->Filter()->Clear(); 2372 category->RegexFilter()->Clear(); 2373 } 2374 2375 result.SetStatus(eReturnStatusSuccessFinishResult); 2376 return result.Succeeded(); 2377 } 2378 2379 }; 2380 2381 OptionDefinition 2382 CommandObjectTypeSynthClear::CommandOptions::g_option_table[] = 2383 { 2384 { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeNone, "Clear every category."}, 2385 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 2386 }; 2387 2388 //------------------------------------------------------------------------- 2389 // CommandObjectTypeSynthAdd 2390 //------------------------------------------------------------------------- 2391 2392 static const char *g_synth_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" 2393 "You must define a Python class with these methods:\n" 2394 " def __init__(self, valobj, dict):\n" 2395 " def num_children(self):\n" 2396 " def get_child_at_index(self, index):\n" 2397 " def get_child_index(self, name):\n" 2398 "Optionally, you can also define a method:\n" 2399 " def update(self):\n" 2400 "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" 2401 "class synthProvider:"; 2402 2403 class TypeSynthAddInputReader : public InputReaderEZ 2404 { 2405 private: 2406 DISALLOW_COPY_AND_ASSIGN (TypeSynthAddInputReader); 2407 public: 2408 TypeSynthAddInputReader(Debugger& debugger) : 2409 InputReaderEZ(debugger) 2410 {} 2411 2412 virtual 2413 ~TypeSynthAddInputReader() 2414 { 2415 } 2416 2417 virtual void ActivateHandler(HandlerData& data) 2418 { 2419 StreamSP out_stream = data.GetOutStream(); 2420 bool batch_mode = data.GetBatchMode(); 2421 if (!batch_mode) 2422 { 2423 out_stream->Printf ("%s\n", g_synth_addreader_instructions); 2424 if (data.reader.GetPrompt()) 2425 out_stream->Printf ("%s", data.reader.GetPrompt()); 2426 out_stream->Flush(); 2427 } 2428 } 2429 2430 virtual void ReactivateHandler(HandlerData& data) 2431 { 2432 StreamSP out_stream = data.GetOutStream(); 2433 bool batch_mode = data.GetBatchMode(); 2434 if (data.reader.GetPrompt() && !batch_mode) 2435 { 2436 out_stream->Printf ("%s", data.reader.GetPrompt()); 2437 out_stream->Flush(); 2438 } 2439 } 2440 virtual void GotTokenHandler(HandlerData& data) 2441 { 2442 StreamSP out_stream = data.GetOutStream(); 2443 bool batch_mode = data.GetBatchMode(); 2444 if (data.bytes && data.bytes_len && data.baton) 2445 { 2446 ((SynthAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len); 2447 } 2448 if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode) 2449 { 2450 out_stream->Printf ("%s", data.reader.GetPrompt()); 2451 out_stream->Flush(); 2452 } 2453 } 2454 virtual void InterruptHandler(HandlerData& data) 2455 { 2456 StreamSP out_stream = data.GetOutStream(); 2457 bool batch_mode = data.GetBatchMode(); 2458 data.reader.SetIsDone (true); 2459 if (!batch_mode) 2460 { 2461 out_stream->Printf ("Warning: No command attached to breakpoint.\n"); 2462 out_stream->Flush(); 2463 } 2464 } 2465 virtual void EOFHandler(HandlerData& data) 2466 { 2467 data.reader.SetIsDone (true); 2468 } 2469 virtual void DoneHandler(HandlerData& data) 2470 { 2471 StreamSP out_stream = data.GetOutStream(); 2472 SynthAddOptions *options_ptr = ((SynthAddOptions*)data.baton); 2473 if (!options_ptr) 2474 { 2475 out_stream->Printf ("Internal error #1: no script attached.\n"); 2476 out_stream->Flush(); 2477 return; 2478 } 2479 2480 SynthAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope 2481 2482 ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 2483 if (!interpreter) 2484 { 2485 out_stream->Printf ("Internal error #2: no script attached.\n"); 2486 out_stream->Flush(); 2487 return; 2488 } 2489 StringList class_name_sl; 2490 if (!interpreter->GenerateTypeSynthClass (options->m_user_source, 2491 class_name_sl)) 2492 { 2493 out_stream->Printf ("Internal error #3: no script attached.\n"); 2494 out_stream->Flush(); 2495 return; 2496 } 2497 if (class_name_sl.GetSize() == 0) 2498 { 2499 out_stream->Printf ("Internal error #4: no script attached.\n"); 2500 out_stream->Flush(); 2501 return; 2502 } 2503 const char *class_name = class_name_sl.GetStringAtIndex(0); 2504 if (!class_name || !class_name[0]) 2505 { 2506 out_stream->Printf ("Internal error #5: no script attached.\n"); 2507 out_stream->Flush(); 2508 return; 2509 } 2510 2511 // everything should be fine now, let's add the synth provider class 2512 2513 SyntheticChildrenSP synth_provider; 2514 synth_provider.reset(new SyntheticScriptProvider(options->m_cascade, 2515 options->m_skip_pointers, 2516 options->m_skip_references, 2517 std::string(class_name))); 2518 2519 2520 lldb::FormatCategorySP category; 2521 Debugger::Formatting::Categories::Get(ConstString(options->m_category), category); 2522 2523 for (size_t i = 0; i < options->m_target_types.GetSize(); i++) { 2524 const char *type_name = options->m_target_types.GetStringAtIndex(i); 2525 ConstString typeCS(type_name); 2526 if (typeCS) 2527 CommandObjectTypeSynthAdd::AddSynth(typeCS, 2528 synth_provider, 2529 options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth, 2530 options->m_category, 2531 NULL); 2532 else 2533 { 2534 out_stream->Printf ("Internal error #6: no script attached.\n"); 2535 out_stream->Flush(); 2536 return; 2537 } 2538 } 2539 } 2540 }; 2541 2542 void 2543 CommandObjectTypeSynthAdd::CollectPythonScript (SynthAddOptions *options, 2544 CommandReturnObject &result) 2545 { 2546 InputReaderSP reader_sp (new TypeSynthAddInputReader(m_interpreter.GetDebugger())); 2547 if (reader_sp && options) 2548 { 2549 2550 InputReaderEZ::InitializationParameters ipr; 2551 2552 Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt(" "))); 2553 if (err.Success()) 2554 { 2555 m_interpreter.GetDebugger().PushInputReader (reader_sp); 2556 result.SetStatus (eReturnStatusSuccessFinishNoResult); 2557 } 2558 else 2559 { 2560 result.AppendError (err.AsCString()); 2561 result.SetStatus (eReturnStatusFailed); 2562 } 2563 } 2564 else 2565 { 2566 result.AppendError("out of memory"); 2567 result.SetStatus (eReturnStatusFailed); 2568 } 2569 } 2570 2571 bool 2572 CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result) 2573 { 2574 SynthAddOptions *options = new SynthAddOptions ( m_options.m_skip_pointers, 2575 m_options.m_skip_references, 2576 m_options.m_cascade, 2577 m_options.m_regex, 2578 m_options.m_category); 2579 2580 const size_t argc = command.GetArgumentCount(); 2581 2582 for (size_t i = 0; i < argc; i++) { 2583 const char* typeA = command.GetArgumentAtIndex(i); 2584 if (typeA && *typeA) 2585 options->m_target_types << typeA; 2586 else 2587 { 2588 result.AppendError("empty typenames not allowed"); 2589 result.SetStatus(eReturnStatusFailed); 2590 return false; 2591 } 2592 } 2593 2594 CollectPythonScript(options,result); 2595 return result.Succeeded(); 2596 } 2597 2598 bool 2599 CommandObjectTypeSynthAdd::Execute_ChildrenList (Args& command, CommandReturnObject &result) 2600 { 2601 const size_t argc = command.GetArgumentCount(); 2602 2603 if (argc < 1) 2604 { 2605 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 2606 result.SetStatus(eReturnStatusFailed); 2607 return false; 2608 } 2609 2610 if (m_options.m_expr_paths.size() == 0) 2611 { 2612 result.AppendErrorWithFormat ("%s needs one or more children.\n", m_cmd_name.c_str()); 2613 result.SetStatus(eReturnStatusFailed); 2614 return false; 2615 } 2616 2617 SyntheticChildrenSP entry; 2618 2619 SyntheticFilter* impl = new SyntheticFilter(m_options.m_cascade, 2620 m_options.m_skip_pointers, 2621 m_options.m_skip_references); 2622 2623 entry.reset(impl); 2624 2625 // go through the expression paths 2626 CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end(); 2627 2628 for (begin = m_options.m_expr_paths.begin(); begin != end; begin++) 2629 impl->AddExpressionPath(*begin); 2630 2631 2632 // now I have a valid provider, let's add it to every type 2633 2634 lldb::FormatCategorySP category; 2635 Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category); 2636 2637 for (size_t i = 0; i < argc; i++) { 2638 const char* typeA = command.GetArgumentAtIndex(i); 2639 ConstString typeCS(typeA); 2640 if (typeCS) 2641 AddSynth(typeCS, 2642 entry, 2643 m_options.m_regex ? eRegexSynth : eRegularSynth, 2644 m_options.m_category, 2645 NULL); 2646 else 2647 { 2648 result.AppendError("empty typenames not allowed"); 2649 result.SetStatus(eReturnStatusFailed); 2650 return false; 2651 } 2652 } 2653 2654 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2655 return result.Succeeded(); 2656 } 2657 2658 bool 2659 CommandObjectTypeSynthAdd::Execute_PythonClass (Args& command, CommandReturnObject &result) 2660 { 2661 const size_t argc = command.GetArgumentCount(); 2662 2663 if (argc < 1) 2664 { 2665 result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); 2666 result.SetStatus(eReturnStatusFailed); 2667 return false; 2668 } 2669 2670 if (m_options.m_class_name.empty() && !m_options.m_input_python) 2671 { 2672 result.AppendErrorWithFormat ("%s needs either a Python class name or -P to directly input Python code.\n", m_cmd_name.c_str()); 2673 result.SetStatus(eReturnStatusFailed); 2674 return false; 2675 } 2676 2677 SyntheticChildrenSP entry; 2678 2679 SyntheticScriptProvider* impl = new SyntheticScriptProvider(m_options.m_cascade, 2680 m_options.m_skip_pointers, 2681 m_options.m_skip_references, 2682 m_options.m_class_name); 2683 2684 entry.reset(impl); 2685 2686 // now I have a valid provider, let's add it to every type 2687 2688 lldb::FormatCategorySP category; 2689 Debugger::Formatting::Categories::Get(ConstString(m_options.m_category), category); 2690 2691 for (size_t i = 0; i < argc; i++) { 2692 const char* typeA = command.GetArgumentAtIndex(i); 2693 ConstString typeCS(typeA); 2694 if (typeCS) 2695 AddSynth(typeCS, 2696 entry, 2697 m_options.m_regex ? eRegexSynth : eRegularSynth, 2698 m_options.m_category, 2699 NULL); 2700 else 2701 { 2702 result.AppendError("empty typenames not allowed"); 2703 result.SetStatus(eReturnStatusFailed); 2704 return false; 2705 } 2706 } 2707 2708 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2709 return result.Succeeded(); 2710 } 2711 2712 CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd (CommandInterpreter &interpreter) : 2713 CommandObject (interpreter, 2714 "type synthetic add", 2715 "Add a new synthetic provider for a type.", 2716 NULL), m_options (interpreter) 2717 { 2718 CommandArgumentEntry type_arg; 2719 CommandArgumentData type_style_arg; 2720 2721 type_style_arg.arg_type = eArgTypeName; 2722 type_style_arg.arg_repetition = eArgRepeatPlus; 2723 2724 type_arg.push_back (type_style_arg); 2725 2726 m_arguments.push_back (type_arg); 2727 2728 } 2729 2730 bool 2731 CommandObjectTypeSynthAdd::AddSynth(const ConstString& type_name, 2732 SyntheticChildrenSP entry, 2733 SynthFormatType type, 2734 const char* category_name, 2735 Error* error) 2736 { 2737 lldb::FormatCategorySP category; 2738 Debugger::Formatting::Categories::Get(ConstString(category_name), category); 2739 2740 if (type == eRegexSynth) 2741 { 2742 RegularExpressionSP typeRX(new RegularExpression()); 2743 if (!typeRX->Compile(type_name.GetCString())) 2744 { 2745 if (error) 2746 error->SetErrorString("regex format error (maybe this is not really a regex?)"); 2747 return false; 2748 } 2749 2750 category->RegexFilter()->Delete(type_name.GetCString()); 2751 category->RegexFilter()->Add(typeRX, entry); 2752 2753 return true; 2754 } 2755 else 2756 { 2757 category->Filter()->Add(type_name.GetCString(), entry); 2758 return true; 2759 } 2760 } 2761 2762 bool 2763 CommandObjectTypeSynthAdd::Execute (Args& command, CommandReturnObject &result) 2764 { 2765 if (m_options.handwrite_python) 2766 return Execute_HandwritePython(command, result); 2767 else if (m_options.is_class_based) 2768 return Execute_PythonClass(command, result); 2769 else if (m_options.has_child_list) 2770 return Execute_ChildrenList(command, result); 2771 else 2772 { 2773 result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line"); 2774 result.SetStatus(eReturnStatusFailed); 2775 return false; 2776 } 2777 } 2778 2779 OptionDefinition 2780 CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] = 2781 { 2782 { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade to derived typedefs."}, 2783 { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, 2784 { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, 2785 { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, 2786 { LLDB_OPT_SET_1, false, "child", 'c', required_argument, NULL, 0, eArgTypeName, "Include this expression path in the synthetic view."}, 2787 { LLDB_OPT_SET_2, false, "python-class", 'l', required_argument, NULL, 0, eArgTypeName, "Use this Python class to produce synthetic children."}, 2788 { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children."}, 2789 { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, 2790 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 2791 }; 2792 2793 class CommandObjectTypeFormat : public CommandObjectMultiword 2794 { 2795 public: 2796 CommandObjectTypeFormat (CommandInterpreter &interpreter) : 2797 CommandObjectMultiword (interpreter, 2798 "type format", 2799 "A set of commands for editing variable value display options", 2800 "type format [<sub-command-options>] ") 2801 { 2802 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeFormatAdd (interpreter))); 2803 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeFormatClear (interpreter))); 2804 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeFormatDelete (interpreter))); 2805 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeFormatList (interpreter))); 2806 } 2807 2808 2809 ~CommandObjectTypeFormat () 2810 { 2811 } 2812 }; 2813 2814 class CommandObjectTypeSynth : public CommandObjectMultiword 2815 { 2816 public: 2817 CommandObjectTypeSynth (CommandInterpreter &interpreter) : 2818 CommandObjectMultiword (interpreter, 2819 "type synthetic", 2820 "A set of commands for operating on synthetic type representations", 2821 "type synthetic [<sub-command-options>] ") 2822 { 2823 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSynthAdd (interpreter))); 2824 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSynthClear (interpreter))); 2825 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSynthDelete (interpreter))); 2826 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSynthList (interpreter))); 2827 } 2828 2829 2830 ~CommandObjectTypeSynth () 2831 { 2832 } 2833 }; 2834 2835 class CommandObjectTypeCategory : public CommandObjectMultiword 2836 { 2837 public: 2838 CommandObjectTypeCategory (CommandInterpreter &interpreter) : 2839 CommandObjectMultiword (interpreter, 2840 "type category", 2841 "A set of commands for operating on categories", 2842 "type category [<sub-command-options>] ") 2843 { 2844 LoadSubCommand ("enable", CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter))); 2845 LoadSubCommand ("disable", CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter))); 2846 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter))); 2847 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeCategoryList (interpreter))); 2848 } 2849 2850 2851 ~CommandObjectTypeCategory () 2852 { 2853 } 2854 }; 2855 2856 class CommandObjectTypeSummary : public CommandObjectMultiword 2857 { 2858 public: 2859 CommandObjectTypeSummary (CommandInterpreter &interpreter) : 2860 CommandObjectMultiword (interpreter, 2861 "type summary", 2862 "A set of commands for editing variable summary display options", 2863 "type summary [<sub-command-options>] ") 2864 { 2865 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter))); 2866 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter))); 2867 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter))); 2868 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); 2869 } 2870 2871 2872 ~CommandObjectTypeSummary () 2873 { 2874 } 2875 }; 2876 2877 //------------------------------------------------------------------------- 2878 // CommandObjectType 2879 //------------------------------------------------------------------------- 2880 2881 CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) : 2882 CommandObjectMultiword (interpreter, 2883 "type", 2884 "A set of commands for operating on the type system", 2885 "type [<sub-command-options>]") 2886 { 2887 LoadSubCommand ("category", CommandObjectSP (new CommandObjectTypeCategory (interpreter))); 2888 LoadSubCommand ("format", CommandObjectSP (new CommandObjectTypeFormat (interpreter))); 2889 LoadSubCommand ("summary", CommandObjectSP (new CommandObjectTypeSummary (interpreter))); 2890 LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter))); 2891 } 2892 2893 2894 CommandObjectType::~CommandObjectType () 2895 { 2896 } 2897 2898 2899