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