1 //===-- OptionValueProperties.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 "lldb/Interpreter/OptionValueProperties.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Core/Flags.h" 17 #include "lldb/Core/Stream.h" 18 #include "lldb/Core/StringList.h" 19 #include "lldb/Core/UserSettingsController.h" 20 #include "lldb/Interpreter/Args.h" 21 #include "lldb/Interpreter/OptionValues.h" 22 #include "lldb/Interpreter/Property.h" 23 24 using namespace lldb; 25 using namespace lldb_private; 26 27 28 OptionValueProperties::OptionValueProperties (const ConstString &name) : 29 OptionValue (), 30 m_name (name), 31 m_properties (), 32 m_name_to_index () 33 { 34 } 35 36 OptionValueProperties::OptionValueProperties (const OptionValueProperties &global_properties) : 37 OptionValue (global_properties), 38 std::enable_shared_from_this<OptionValueProperties> (), 39 m_name (global_properties.m_name), 40 m_properties (global_properties.m_properties), 41 m_name_to_index (global_properties.m_name_to_index) 42 { 43 // We now have an exact copy of "global_properties". We need to now 44 // find all non-global settings and copy the property values so that 45 // all non-global settings get new OptionValue instances created for 46 // them. 47 const size_t num_properties = m_properties.size(); 48 for (size_t i=0; i<num_properties; ++i) 49 { 50 // Duplicate any values that are not global when constructing properties from 51 // a global copy 52 if (m_properties[i].IsGlobal() == false) 53 { 54 lldb::OptionValueSP new_value_sp (m_properties[i].GetValue()->DeepCopy()); 55 m_properties[i].SetOptionValue(new_value_sp); 56 } 57 } 58 } 59 60 61 62 size_t 63 OptionValueProperties::GetNumProperties() const 64 { 65 return m_properties.size(); 66 } 67 68 69 void 70 OptionValueProperties::Initialize (const PropertyDefinition *defs) 71 { 72 for (size_t i=0; defs[i].name; ++i) 73 { 74 Property property(defs[i]); 75 assert(property.IsValid()); 76 m_name_to_index.Append(property.GetName().GetCString(),m_properties.size()); 77 property.GetValue()->SetParent(shared_from_this()); 78 m_properties.push_back(property); 79 } 80 m_name_to_index.Sort(); 81 } 82 83 void 84 OptionValueProperties::SetValueChangedCallback (uint32_t property_idx, 85 OptionValueChangedCallback callback, 86 void *baton) 87 { 88 Property *property = ProtectedGetPropertyAtIndex (property_idx); 89 if (property) 90 property->SetValueChangedCallback (callback, baton); 91 } 92 93 void 94 OptionValueProperties::AppendProperty(const ConstString &name, 95 const ConstString &desc, 96 bool is_global, 97 const OptionValueSP &value_sp) 98 { 99 Property property(name, desc, is_global, value_sp); 100 m_name_to_index.Append(name.GetCString(),m_properties.size()); 101 m_properties.push_back(property); 102 value_sp->SetParent (shared_from_this()); 103 m_name_to_index.Sort(); 104 } 105 106 107 108 //bool 109 //OptionValueProperties::GetQualifiedName (Stream &strm) 110 //{ 111 // bool dumped_something = false; 112 //// lldb::OptionValuePropertiesSP parent_sp(GetParent ()); 113 //// if (parent_sp) 114 //// { 115 //// parent_sp->GetQualifiedName (strm); 116 //// strm.PutChar('.'); 117 //// dumped_something = true; 118 //// } 119 // if (m_name) 120 // { 121 // strm << m_name; 122 // dumped_something = true; 123 // } 124 // return dumped_something; 125 //} 126 // 127 lldb::OptionValueSP 128 OptionValueProperties::GetValueForKey (const ExecutionContext *exe_ctx, 129 const ConstString &key, 130 bool will_modify) const 131 { 132 lldb::OptionValueSP value_sp; 133 size_t idx = m_name_to_index.Find (key.GetCString(), SIZE_MAX); 134 if (idx < m_properties.size()) 135 value_sp = GetPropertyAtIndex(exe_ctx, will_modify, idx)->GetValue(); 136 return value_sp; 137 } 138 139 lldb::OptionValueSP 140 OptionValueProperties::GetSubValue (const ExecutionContext *exe_ctx, 141 const char *name, 142 bool will_modify, 143 Error &error) const 144 { 145 lldb::OptionValueSP value_sp; 146 147 if (name && name[0]) 148 { 149 const char *sub_name = nullptr; 150 ConstString key; 151 size_t key_len = ::strcspn (name, ".[{"); 152 153 if (name[key_len]) 154 { 155 key.SetCStringWithLength (name, key_len); 156 sub_name = name + key_len; 157 } 158 else 159 key.SetCString (name); 160 161 value_sp = GetValueForKey (exe_ctx, key, will_modify); 162 if (sub_name && value_sp) 163 { 164 switch (sub_name[0]) 165 { 166 case '.': 167 { 168 lldb::OptionValueSP return_val_sp; 169 return_val_sp = value_sp->GetSubValue (exe_ctx, sub_name + 1, will_modify, error); 170 if (!return_val_sp) 171 { 172 if (Properties::IsSettingExperimental(sub_name + 1)) 173 { 174 size_t experimental_len = strlen(Properties::GetExperimentalSettingsName()); 175 if (*(sub_name + experimental_len + 1) == '.') 176 return_val_sp = value_sp->GetSubValue(exe_ctx, sub_name + experimental_len + 2, will_modify, error); 177 // It isn't an error if an experimental setting is not present. 178 if (!return_val_sp) 179 error.Clear(); 180 } 181 } 182 return return_val_sp; 183 } 184 case '{': 185 // Predicate matching for predicates like 186 // "<setting-name>{<predicate>}" 187 // strings are parsed by the current OptionValueProperties subclass 188 // to mean whatever they want to. For instance a subclass of 189 // OptionValueProperties for a lldb_private::Target might implement: 190 // "target.run-args{arch==i386}" -- only set run args if the arch is i386 191 // "target.run-args{path=/tmp/a/b/c/a.out}" -- only set run args if the path matches 192 // "target.run-args{basename==test&&arch==x86_64}" -- only set run args if executable basename is "test" and arch is "x86_64" 193 if (sub_name[1]) 194 { 195 const char *predicate_start = sub_name + 1; 196 const char *predicate_end = strchr(predicate_start, '}'); 197 if (predicate_end) 198 { 199 std::string predicate(predicate_start, predicate_end); 200 if (PredicateMatches(exe_ctx, predicate.c_str())) 201 { 202 if (predicate_end[1]) 203 { 204 // Still more subvalue string to evaluate 205 return value_sp->GetSubValue (exe_ctx, predicate_end + 1, will_modify, error); 206 } 207 else 208 { 209 // We have a match! 210 break; 211 } 212 } 213 } 214 } 215 // Predicate didn't match or wasn't correctly formed 216 value_sp.reset(); 217 break; 218 219 case '[': 220 // Array or dictionary access for subvalues like: 221 // "[12]" -- access 12th array element 222 // "['hello']" -- dictionary access of key named hello 223 return value_sp->GetSubValue (exe_ctx, sub_name, will_modify, error); 224 225 default: 226 value_sp.reset(); 227 break; 228 } 229 } 230 } 231 return value_sp; 232 } 233 234 Error 235 OptionValueProperties::SetSubValue (const ExecutionContext *exe_ctx, 236 VarSetOperationType op, 237 const char *name, 238 const char *value) 239 { 240 Error error; 241 const bool will_modify = true; 242 lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, name, will_modify, error)); 243 if (value_sp) 244 error = value_sp->SetValueFromString(value ? llvm::StringRef(value) : llvm::StringRef(), op); 245 else 246 { 247 if (error.AsCString() == nullptr) 248 error.SetErrorStringWithFormat("invalid value path '%s'", name); 249 } 250 return error; 251 } 252 253 254 ConstString 255 OptionValueProperties::GetPropertyNameAtIndex (uint32_t idx) const 256 { 257 const Property *property = GetPropertyAtIndex(nullptr, false, idx); 258 if (property) 259 return property->GetName(); 260 return ConstString(); 261 262 } 263 264 const char * 265 OptionValueProperties::GetPropertyDescriptionAtIndex (uint32_t idx) const 266 { 267 const Property *property = GetPropertyAtIndex(nullptr, false, idx); 268 if (property) 269 return property->GetDescription(); 270 return nullptr; 271 } 272 273 uint32_t 274 OptionValueProperties::GetPropertyIndex (const ConstString &name) const 275 { 276 return m_name_to_index.Find (name.GetCString(), SIZE_MAX); 277 } 278 279 const Property * 280 OptionValueProperties::GetProperty (const ExecutionContext *exe_ctx, bool will_modify, const ConstString &name) const 281 { 282 return GetPropertyAtIndex (exe_ctx, will_modify, m_name_to_index.Find (name.GetCString(), SIZE_MAX)); 283 } 284 285 const Property * 286 OptionValueProperties::GetPropertyAtIndex (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const 287 { 288 return ProtectedGetPropertyAtIndex (idx); 289 } 290 291 lldb::OptionValueSP 292 OptionValueProperties::GetPropertyValueAtIndex (const ExecutionContext *exe_ctx, 293 bool will_modify, 294 uint32_t idx) const 295 { 296 const Property *setting = GetPropertyAtIndex (exe_ctx, will_modify, idx); 297 if (setting) 298 return setting->GetValue(); 299 return OptionValueSP(); 300 } 301 302 OptionValuePathMappings * 303 OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const 304 { 305 OptionValueSP value_sp(GetPropertyValueAtIndex (exe_ctx, will_modify, idx)); 306 if (value_sp) 307 return value_sp->GetAsPathMappings(); 308 return nullptr; 309 } 310 311 OptionValueFileSpecList * 312 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const 313 { 314 OptionValueSP value_sp(GetPropertyValueAtIndex (exe_ctx, will_modify, idx)); 315 if (value_sp) 316 return value_sp->GetAsFileSpecList(); 317 return nullptr; 318 } 319 320 OptionValueArch * 321 OptionValueProperties::GetPropertyAtIndexAsOptionValueArch (const ExecutionContext *exe_ctx, uint32_t idx) const 322 { 323 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 324 if (property) 325 return property->GetValue()->GetAsArch(); 326 return nullptr; 327 } 328 329 OptionValueLanguage * 330 OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage (const ExecutionContext *exe_ctx, uint32_t idx) const 331 { 332 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 333 if (property) 334 return property->GetValue()->GetAsLanguage(); 335 return nullptr; 336 } 337 338 bool 339 OptionValueProperties::GetPropertyAtIndexAsArgs (const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const 340 { 341 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 342 if (property) 343 { 344 OptionValue *value = property->GetValue().get(); 345 if (value) 346 { 347 const OptionValueArray *array = value->GetAsArray(); 348 if (array) 349 return array->GetArgs(args); 350 else 351 { 352 const OptionValueDictionary *dict = value->GetAsDictionary(); 353 if (dict) 354 return dict->GetArgs(args); 355 } 356 } 357 } 358 return false; 359 } 360 361 bool 362 OptionValueProperties::SetPropertyAtIndexFromArgs (const ExecutionContext *exe_ctx, uint32_t idx, const Args &args) 363 { 364 const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); 365 if (property) 366 { 367 OptionValue *value = property->GetValue().get(); 368 if (value) 369 { 370 OptionValueArray *array = value->GetAsArray(); 371 if (array) 372 return array->SetArgs(args, eVarSetOperationAssign).Success(); 373 else 374 { 375 OptionValueDictionary *dict = value->GetAsDictionary(); 376 if (dict) 377 return dict->SetArgs(args, eVarSetOperationAssign).Success(); 378 } 379 } 380 } 381 return false; 382 } 383 384 bool 385 OptionValueProperties::GetPropertyAtIndexAsBoolean (const ExecutionContext *exe_ctx, uint32_t idx, bool fail_value) const 386 { 387 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 388 if (property) 389 { 390 OptionValue *value = property->GetValue().get(); 391 if (value) 392 return value->GetBooleanValue(fail_value); 393 } 394 return fail_value; 395 } 396 397 bool 398 OptionValueProperties::SetPropertyAtIndexAsBoolean (const ExecutionContext *exe_ctx, uint32_t idx, bool new_value) 399 { 400 const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); 401 if (property) 402 { 403 OptionValue *value = property->GetValue().get(); 404 if (value) 405 { 406 value->SetBooleanValue(new_value); 407 return true; 408 } 409 } 410 return false; 411 } 412 413 OptionValueDictionary * 414 OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary (const ExecutionContext *exe_ctx, uint32_t idx) const 415 { 416 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 417 if (property) 418 return property->GetValue()->GetAsDictionary(); 419 return nullptr; 420 } 421 422 int64_t 423 OptionValueProperties::GetPropertyAtIndexAsEnumeration (const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const 424 { 425 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 426 if (property) 427 { 428 OptionValue *value = property->GetValue().get(); 429 if (value) 430 return value->GetEnumerationValue(fail_value); 431 } 432 return fail_value; 433 } 434 435 bool 436 OptionValueProperties::SetPropertyAtIndexAsEnumeration (const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) 437 { 438 const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); 439 if (property) 440 { 441 OptionValue *value = property->GetValue().get(); 442 if (value) 443 return value->SetEnumerationValue(new_value); 444 } 445 return false; 446 } 447 448 const FormatEntity::Entry * 449 OptionValueProperties::GetPropertyAtIndexAsFormatEntity (const ExecutionContext *exe_ctx, uint32_t idx) 450 { 451 const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); 452 if (property) 453 { 454 OptionValue *value = property->GetValue().get(); 455 if (value) 456 return value->GetFormatEntity(); 457 } 458 return nullptr; 459 } 460 461 OptionValueFileSpec * 462 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const 463 { 464 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 465 if (property) 466 { 467 OptionValue *value = property->GetValue().get(); 468 if (value) 469 return value->GetAsFileSpec(); 470 } 471 return nullptr; 472 } 473 474 475 FileSpec 476 OptionValueProperties::GetPropertyAtIndexAsFileSpec (const ExecutionContext *exe_ctx, uint32_t idx) const 477 { 478 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 479 if (property) 480 { 481 OptionValue *value = property->GetValue().get(); 482 if (value) 483 return value->GetFileSpecValue(); 484 } 485 return FileSpec(); 486 } 487 488 489 bool 490 OptionValueProperties::SetPropertyAtIndexAsFileSpec (const ExecutionContext *exe_ctx, uint32_t idx, const FileSpec &new_file_spec) 491 { 492 const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); 493 if (property) 494 { 495 OptionValue *value = property->GetValue().get(); 496 if (value) 497 return value->SetFileSpecValue(new_file_spec); 498 } 499 return false; 500 } 501 502 const RegularExpression * 503 OptionValueProperties::GetPropertyAtIndexAsOptionValueRegex (const ExecutionContext *exe_ctx, uint32_t idx) const 504 { 505 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 506 if (property) 507 { 508 OptionValue *value = property->GetValue().get(); 509 if (value) 510 return value->GetRegexValue(); 511 } 512 return nullptr; 513 } 514 515 OptionValueSInt64 * 516 OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64 (const ExecutionContext *exe_ctx, uint32_t idx) const 517 { 518 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 519 if (property) 520 { 521 OptionValue *value = property->GetValue().get(); 522 if (value) 523 return value->GetAsSInt64(); 524 } 525 return nullptr; 526 } 527 528 int64_t 529 OptionValueProperties::GetPropertyAtIndexAsSInt64 (const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const 530 { 531 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 532 if (property) 533 { 534 OptionValue *value = property->GetValue().get(); 535 if (value) 536 return value->GetSInt64Value(fail_value); 537 } 538 return fail_value; 539 } 540 541 bool 542 OptionValueProperties::SetPropertyAtIndexAsSInt64 (const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) 543 { 544 const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); 545 if (property) 546 { 547 OptionValue *value = property->GetValue().get(); 548 if (value) 549 return value->SetSInt64Value(new_value); 550 } 551 return false; 552 } 553 554 const char * 555 OptionValueProperties::GetPropertyAtIndexAsString (const ExecutionContext *exe_ctx, uint32_t idx, const char *fail_value) const 556 { 557 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 558 if (property) 559 { 560 OptionValue *value = property->GetValue().get(); 561 if (value) 562 return value->GetStringValue(fail_value); 563 } 564 return fail_value; 565 } 566 567 bool 568 OptionValueProperties::SetPropertyAtIndexAsString (const ExecutionContext *exe_ctx, uint32_t idx, const char *new_value) 569 { 570 const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); 571 if (property) 572 { 573 OptionValue *value = property->GetValue().get(); 574 if (value) 575 return value->SetStringValue(new_value); 576 } 577 return false; 578 } 579 580 OptionValueString * 581 OptionValueProperties::GetPropertyAtIndexAsOptionValueString (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const 582 { 583 OptionValueSP value_sp(GetPropertyValueAtIndex (exe_ctx, will_modify, idx)); 584 if (value_sp) 585 return value_sp->GetAsString(); 586 return nullptr; 587 } 588 589 590 uint64_t 591 OptionValueProperties::GetPropertyAtIndexAsUInt64 (const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const 592 { 593 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 594 if (property) 595 { 596 OptionValue *value = property->GetValue().get(); 597 if (value) 598 return value->GetUInt64Value(fail_value); 599 } 600 return fail_value; 601 } 602 603 bool 604 OptionValueProperties::SetPropertyAtIndexAsUInt64 (const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value) 605 { 606 const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); 607 if (property) 608 { 609 OptionValue *value = property->GetValue().get(); 610 if (value) 611 return value->SetUInt64Value(new_value); 612 } 613 return false; 614 } 615 616 bool 617 OptionValueProperties::Clear () 618 { 619 const size_t num_properties = m_properties.size(); 620 for (size_t i=0; i<num_properties; ++i) 621 m_properties[i].GetValue()->Clear(); 622 return true; 623 } 624 625 626 Error 627 OptionValueProperties::SetValueFromString (llvm::StringRef value, VarSetOperationType op) 628 { 629 Error error; 630 631 // Args args(value_cstr); 632 // const size_t argc = args.GetArgumentCount(); 633 switch (op) 634 { 635 case eVarSetOperationClear: 636 Clear (); 637 break; 638 639 case eVarSetOperationReplace: 640 case eVarSetOperationAssign: 641 case eVarSetOperationRemove: 642 case eVarSetOperationInsertBefore: 643 case eVarSetOperationInsertAfter: 644 case eVarSetOperationAppend: 645 case eVarSetOperationInvalid: 646 error = OptionValue::SetValueFromString (value, op); 647 break; 648 } 649 650 return error; 651 } 652 653 void 654 OptionValueProperties::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) 655 { 656 const size_t num_properties = m_properties.size(); 657 for (size_t i=0; i<num_properties; ++i) 658 { 659 const Property *property = GetPropertyAtIndex(exe_ctx, false, i); 660 if (property) 661 { 662 OptionValue *option_value = property->GetValue().get(); 663 assert (option_value); 664 const bool transparent_value = option_value->ValueIsTransparent (); 665 property->Dump (exe_ctx, 666 strm, 667 dump_mask); 668 if (!transparent_value) 669 strm.EOL(); 670 } 671 } 672 } 673 674 Error 675 OptionValueProperties::DumpPropertyValue (const ExecutionContext *exe_ctx, 676 Stream &strm, 677 const char *property_path, 678 uint32_t dump_mask) 679 { 680 Error error; 681 const bool will_modify = false; 682 lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, property_path, will_modify, error)); 683 if (value_sp) 684 { 685 if (!value_sp->ValueIsTransparent ()) 686 { 687 if (dump_mask & eDumpOptionName) 688 strm.PutCString (property_path); 689 if (dump_mask & ~eDumpOptionName) 690 strm.PutChar (' '); 691 } 692 value_sp->DumpValue (exe_ctx, strm, dump_mask); 693 } 694 return error; 695 } 696 697 lldb::OptionValueSP 698 OptionValueProperties::DeepCopy () const 699 { 700 assert(!"this shouldn't happen"); 701 return lldb::OptionValueSP(); 702 } 703 704 const Property * 705 OptionValueProperties::GetPropertyAtPath (const ExecutionContext *exe_ctx, 706 bool will_modify, 707 const char *name) const 708 { 709 const Property *property = nullptr; 710 if (name && name[0]) 711 { 712 const char *sub_name = nullptr; 713 ConstString key; 714 size_t key_len = ::strcspn (name, ".[{"); 715 716 if (name[key_len]) 717 { 718 key.SetCStringWithLength (name, key_len); 719 sub_name = name + key_len; 720 } 721 else 722 key.SetCString (name); 723 724 property = GetProperty (exe_ctx, will_modify, key); 725 if (sub_name && property) 726 { 727 if (sub_name[0] == '.') 728 { 729 OptionValueProperties *sub_properties = property->GetValue()->GetAsProperties(); 730 if (sub_properties) 731 return sub_properties->GetPropertyAtPath(exe_ctx, will_modify, sub_name + 1); 732 } 733 property = nullptr; 734 } 735 } 736 return property; 737 } 738 739 void 740 OptionValueProperties::DumpAllDescriptions (CommandInterpreter &interpreter, 741 Stream &strm) const 742 { 743 size_t max_name_len = 0; 744 const size_t num_properties = m_properties.size(); 745 for (size_t i=0; i<num_properties; ++i) 746 { 747 const Property *property = ProtectedGetPropertyAtIndex(i); 748 if (property) 749 max_name_len = std::max<size_t>(property->GetName().GetLength(), max_name_len); 750 } 751 for (size_t i=0; i<num_properties; ++i) 752 { 753 const Property *property = ProtectedGetPropertyAtIndex(i); 754 if (property) 755 property->DumpDescription (interpreter, strm, max_name_len, false); 756 } 757 } 758 759 void 760 OptionValueProperties::Apropos (const char *keyword, std::vector<const Property *> &matching_properties) const 761 { 762 const size_t num_properties = m_properties.size(); 763 StreamString strm; 764 for (size_t i=0; i<num_properties; ++i) 765 { 766 const Property *property = ProtectedGetPropertyAtIndex(i); 767 if (property) 768 { 769 const OptionValueProperties *properties = property->GetValue()->GetAsProperties(); 770 if (properties) 771 { 772 properties->Apropos (keyword, matching_properties); 773 } 774 else 775 { 776 bool match = false; 777 const char *name = property->GetName().GetCString(); 778 if (name && ::strcasestr(name, keyword)) 779 match = true; 780 else 781 { 782 const char *desc = property->GetDescription(); 783 if (desc && ::strcasestr(desc, keyword)) 784 match = true; 785 } 786 if (match) 787 { 788 matching_properties.push_back (property); 789 } 790 } 791 } 792 } 793 } 794 795 lldb::OptionValuePropertiesSP 796 OptionValueProperties::GetSubProperty (const ExecutionContext *exe_ctx, 797 const ConstString &name) 798 { 799 lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name, false)); 800 if (option_value_sp) 801 { 802 OptionValueProperties *ov_properties = option_value_sp->GetAsProperties (); 803 if (ov_properties) 804 return ov_properties->shared_from_this(); 805 } 806 return lldb::OptionValuePropertiesSP(); 807 } 808 809 810 811