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 return value_sp->GetSubValue (exe_ctx, sub_name + 1, will_modify, error); 168 169 case '{': 170 // Predicate matching for predicates like 171 // "<setting-name>{<predicate>}" 172 // strings are parsed by the current OptionValueProperties subclass 173 // to mean whatever they want to. For instance a subclass of 174 // OptionValueProperties for a lldb_private::Target might implement: 175 // "target.run-args{arch==i386}" -- only set run args if the arch is i386 176 // "target.run-args{path=/tmp/a/b/c/a.out}" -- only set run args if the path matches 177 // "target.run-args{basename==test&&arch==x86_64}" -- only set run args if executable basename is "test" and arch is "x86_64" 178 if (sub_name[1]) 179 { 180 const char *predicate_start = sub_name + 1; 181 const char *predicate_end = strchr(predicate_start, '}'); 182 if (predicate_end) 183 { 184 std::string predicate(predicate_start, predicate_end); 185 if (PredicateMatches(exe_ctx, predicate.c_str())) 186 { 187 if (predicate_end[1]) 188 { 189 // Still more subvalue string to evaluate 190 return value_sp->GetSubValue (exe_ctx, predicate_end + 1, will_modify, error); 191 } 192 else 193 { 194 // We have a match! 195 break; 196 } 197 } 198 } 199 } 200 // Predicate didn't match or wasn't correctly formed 201 value_sp.reset(); 202 break; 203 204 case '[': 205 // Array or dictionary access for subvalues like: 206 // "[12]" -- access 12th array element 207 // "['hello']" -- dictionary access of key named hello 208 return value_sp->GetSubValue (exe_ctx, sub_name, will_modify, error); 209 210 default: 211 value_sp.reset(); 212 break; 213 } 214 } 215 } 216 return value_sp; 217 } 218 219 Error 220 OptionValueProperties::SetSubValue (const ExecutionContext *exe_ctx, 221 VarSetOperationType op, 222 const char *name, 223 const char *value) 224 { 225 Error error; 226 const bool will_modify = true; 227 lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, name, will_modify, error)); 228 if (value_sp) 229 error = value_sp->SetValueFromString(value ? llvm::StringRef(value) : llvm::StringRef(), op); 230 else 231 { 232 if (error.AsCString() == nullptr) 233 error.SetErrorStringWithFormat("invalid value path '%s'", name); 234 } 235 return error; 236 } 237 238 239 ConstString 240 OptionValueProperties::GetPropertyNameAtIndex (uint32_t idx) const 241 { 242 const Property *property = GetPropertyAtIndex(nullptr, false, idx); 243 if (property) 244 return property->GetName(); 245 return ConstString(); 246 247 } 248 249 const char * 250 OptionValueProperties::GetPropertyDescriptionAtIndex (uint32_t idx) const 251 { 252 const Property *property = GetPropertyAtIndex(nullptr, false, idx); 253 if (property) 254 return property->GetDescription(); 255 return nullptr; 256 } 257 258 uint32_t 259 OptionValueProperties::GetPropertyIndex (const ConstString &name) const 260 { 261 return m_name_to_index.Find (name.GetCString(), SIZE_MAX); 262 } 263 264 const Property * 265 OptionValueProperties::GetProperty (const ExecutionContext *exe_ctx, bool will_modify, const ConstString &name) const 266 { 267 return GetPropertyAtIndex (exe_ctx, will_modify, m_name_to_index.Find (name.GetCString(), SIZE_MAX)); 268 } 269 270 const Property * 271 OptionValueProperties::GetPropertyAtIndex (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const 272 { 273 return ProtectedGetPropertyAtIndex (idx); 274 } 275 276 lldb::OptionValueSP 277 OptionValueProperties::GetPropertyValueAtIndex (const ExecutionContext *exe_ctx, 278 bool will_modify, 279 uint32_t idx) const 280 { 281 const Property *setting = GetPropertyAtIndex (exe_ctx, will_modify, idx); 282 if (setting) 283 return setting->GetValue(); 284 return OptionValueSP(); 285 } 286 287 OptionValuePathMappings * 288 OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const 289 { 290 OptionValueSP value_sp(GetPropertyValueAtIndex (exe_ctx, will_modify, idx)); 291 if (value_sp) 292 return value_sp->GetAsPathMappings(); 293 return nullptr; 294 } 295 296 OptionValueFileSpecList * 297 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const 298 { 299 OptionValueSP value_sp(GetPropertyValueAtIndex (exe_ctx, will_modify, idx)); 300 if (value_sp) 301 return value_sp->GetAsFileSpecList(); 302 return nullptr; 303 } 304 305 OptionValueArch * 306 OptionValueProperties::GetPropertyAtIndexAsOptionValueArch (const ExecutionContext *exe_ctx, uint32_t idx) const 307 { 308 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 309 if (property) 310 return property->GetValue()->GetAsArch(); 311 return nullptr; 312 } 313 314 OptionValueLanguage * 315 OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage (const ExecutionContext *exe_ctx, uint32_t idx) const 316 { 317 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 318 if (property) 319 return property->GetValue()->GetAsLanguage(); 320 return nullptr; 321 } 322 323 bool 324 OptionValueProperties::GetPropertyAtIndexAsArgs (const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const 325 { 326 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 327 if (property) 328 { 329 OptionValue *value = property->GetValue().get(); 330 if (value) 331 { 332 const OptionValueArray *array = value->GetAsArray(); 333 if (array) 334 return array->GetArgs(args); 335 else 336 { 337 const OptionValueDictionary *dict = value->GetAsDictionary(); 338 if (dict) 339 return dict->GetArgs(args); 340 } 341 } 342 } 343 return false; 344 } 345 346 bool 347 OptionValueProperties::SetPropertyAtIndexFromArgs (const ExecutionContext *exe_ctx, uint32_t idx, const Args &args) 348 { 349 const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); 350 if (property) 351 { 352 OptionValue *value = property->GetValue().get(); 353 if (value) 354 { 355 OptionValueArray *array = value->GetAsArray(); 356 if (array) 357 return array->SetArgs(args, eVarSetOperationAssign).Success(); 358 else 359 { 360 OptionValueDictionary *dict = value->GetAsDictionary(); 361 if (dict) 362 return dict->SetArgs(args, eVarSetOperationAssign).Success(); 363 } 364 } 365 } 366 return false; 367 } 368 369 bool 370 OptionValueProperties::GetPropertyAtIndexAsBoolean (const ExecutionContext *exe_ctx, uint32_t idx, bool fail_value) const 371 { 372 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 373 if (property) 374 { 375 OptionValue *value = property->GetValue().get(); 376 if (value) 377 return value->GetBooleanValue(fail_value); 378 } 379 return fail_value; 380 } 381 382 bool 383 OptionValueProperties::SetPropertyAtIndexAsBoolean (const ExecutionContext *exe_ctx, uint32_t idx, bool new_value) 384 { 385 const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); 386 if (property) 387 { 388 OptionValue *value = property->GetValue().get(); 389 if (value) 390 { 391 value->SetBooleanValue(new_value); 392 return true; 393 } 394 } 395 return false; 396 } 397 398 OptionValueDictionary * 399 OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary (const ExecutionContext *exe_ctx, uint32_t idx) const 400 { 401 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 402 if (property) 403 return property->GetValue()->GetAsDictionary(); 404 return nullptr; 405 } 406 407 int64_t 408 OptionValueProperties::GetPropertyAtIndexAsEnumeration (const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const 409 { 410 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 411 if (property) 412 { 413 OptionValue *value = property->GetValue().get(); 414 if (value) 415 return value->GetEnumerationValue(fail_value); 416 } 417 return fail_value; 418 } 419 420 bool 421 OptionValueProperties::SetPropertyAtIndexAsEnumeration (const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) 422 { 423 const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); 424 if (property) 425 { 426 OptionValue *value = property->GetValue().get(); 427 if (value) 428 return value->SetEnumerationValue(new_value); 429 } 430 return false; 431 } 432 433 const FormatEntity::Entry * 434 OptionValueProperties::GetPropertyAtIndexAsFormatEntity (const ExecutionContext *exe_ctx, uint32_t idx) 435 { 436 const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); 437 if (property) 438 { 439 OptionValue *value = property->GetValue().get(); 440 if (value) 441 return value->GetFormatEntity(); 442 } 443 return nullptr; 444 } 445 446 OptionValueFileSpec * 447 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const 448 { 449 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 450 if (property) 451 { 452 OptionValue *value = property->GetValue().get(); 453 if (value) 454 return value->GetAsFileSpec(); 455 } 456 return nullptr; 457 } 458 459 460 FileSpec 461 OptionValueProperties::GetPropertyAtIndexAsFileSpec (const ExecutionContext *exe_ctx, uint32_t idx) const 462 { 463 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 464 if (property) 465 { 466 OptionValue *value = property->GetValue().get(); 467 if (value) 468 return value->GetFileSpecValue(); 469 } 470 return FileSpec(); 471 } 472 473 474 bool 475 OptionValueProperties::SetPropertyAtIndexAsFileSpec (const ExecutionContext *exe_ctx, uint32_t idx, const FileSpec &new_file_spec) 476 { 477 const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); 478 if (property) 479 { 480 OptionValue *value = property->GetValue().get(); 481 if (value) 482 return value->SetFileSpecValue(new_file_spec); 483 } 484 return false; 485 } 486 487 const RegularExpression * 488 OptionValueProperties::GetPropertyAtIndexAsOptionValueRegex (const ExecutionContext *exe_ctx, uint32_t idx) const 489 { 490 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 491 if (property) 492 { 493 OptionValue *value = property->GetValue().get(); 494 if (value) 495 return value->GetRegexValue(); 496 } 497 return nullptr; 498 } 499 500 OptionValueSInt64 * 501 OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64 (const ExecutionContext *exe_ctx, uint32_t idx) const 502 { 503 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 504 if (property) 505 { 506 OptionValue *value = property->GetValue().get(); 507 if (value) 508 return value->GetAsSInt64(); 509 } 510 return nullptr; 511 } 512 513 int64_t 514 OptionValueProperties::GetPropertyAtIndexAsSInt64 (const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const 515 { 516 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 517 if (property) 518 { 519 OptionValue *value = property->GetValue().get(); 520 if (value) 521 return value->GetSInt64Value(fail_value); 522 } 523 return fail_value; 524 } 525 526 bool 527 OptionValueProperties::SetPropertyAtIndexAsSInt64 (const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) 528 { 529 const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); 530 if (property) 531 { 532 OptionValue *value = property->GetValue().get(); 533 if (value) 534 return value->SetSInt64Value(new_value); 535 } 536 return false; 537 } 538 539 const char * 540 OptionValueProperties::GetPropertyAtIndexAsString (const ExecutionContext *exe_ctx, uint32_t idx, const char *fail_value) const 541 { 542 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 543 if (property) 544 { 545 OptionValue *value = property->GetValue().get(); 546 if (value) 547 return value->GetStringValue(fail_value); 548 } 549 return fail_value; 550 } 551 552 bool 553 OptionValueProperties::SetPropertyAtIndexAsString (const ExecutionContext *exe_ctx, uint32_t idx, const char *new_value) 554 { 555 const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); 556 if (property) 557 { 558 OptionValue *value = property->GetValue().get(); 559 if (value) 560 return value->SetStringValue(new_value); 561 } 562 return false; 563 } 564 565 OptionValueString * 566 OptionValueProperties::GetPropertyAtIndexAsOptionValueString (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const 567 { 568 OptionValueSP value_sp(GetPropertyValueAtIndex (exe_ctx, will_modify, idx)); 569 if (value_sp) 570 return value_sp->GetAsString(); 571 return nullptr; 572 } 573 574 575 uint64_t 576 OptionValueProperties::GetPropertyAtIndexAsUInt64 (const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const 577 { 578 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 579 if (property) 580 { 581 OptionValue *value = property->GetValue().get(); 582 if (value) 583 return value->GetUInt64Value(fail_value); 584 } 585 return fail_value; 586 } 587 588 bool 589 OptionValueProperties::SetPropertyAtIndexAsUInt64 (const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value) 590 { 591 const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); 592 if (property) 593 { 594 OptionValue *value = property->GetValue().get(); 595 if (value) 596 return value->SetUInt64Value(new_value); 597 } 598 return false; 599 } 600 601 bool 602 OptionValueProperties::Clear () 603 { 604 const size_t num_properties = m_properties.size(); 605 for (size_t i=0; i<num_properties; ++i) 606 m_properties[i].GetValue()->Clear(); 607 return true; 608 } 609 610 611 Error 612 OptionValueProperties::SetValueFromString (llvm::StringRef value, VarSetOperationType op) 613 { 614 Error error; 615 616 // Args args(value_cstr); 617 // const size_t argc = args.GetArgumentCount(); 618 switch (op) 619 { 620 case eVarSetOperationClear: 621 Clear (); 622 break; 623 624 case eVarSetOperationReplace: 625 case eVarSetOperationAssign: 626 case eVarSetOperationRemove: 627 case eVarSetOperationInsertBefore: 628 case eVarSetOperationInsertAfter: 629 case eVarSetOperationAppend: 630 case eVarSetOperationInvalid: 631 error = OptionValue::SetValueFromString (value, op); 632 break; 633 } 634 635 return error; 636 } 637 638 void 639 OptionValueProperties::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) 640 { 641 const size_t num_properties = m_properties.size(); 642 for (size_t i=0; i<num_properties; ++i) 643 { 644 const Property *property = GetPropertyAtIndex(exe_ctx, false, i); 645 if (property) 646 { 647 OptionValue *option_value = property->GetValue().get(); 648 assert (option_value); 649 const bool transparent_value = option_value->ValueIsTransparent (); 650 property->Dump (exe_ctx, 651 strm, 652 dump_mask); 653 if (!transparent_value) 654 strm.EOL(); 655 } 656 } 657 } 658 659 Error 660 OptionValueProperties::DumpPropertyValue (const ExecutionContext *exe_ctx, 661 Stream &strm, 662 const char *property_path, 663 uint32_t dump_mask) 664 { 665 Error error; 666 const bool will_modify = false; 667 lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, property_path, will_modify, error)); 668 if (value_sp) 669 { 670 if (!value_sp->ValueIsTransparent ()) 671 { 672 if (dump_mask & eDumpOptionName) 673 strm.PutCString (property_path); 674 if (dump_mask & ~eDumpOptionName) 675 strm.PutChar (' '); 676 } 677 value_sp->DumpValue (exe_ctx, strm, dump_mask); 678 } 679 return error; 680 } 681 682 lldb::OptionValueSP 683 OptionValueProperties::DeepCopy () const 684 { 685 assert(!"this shouldn't happen"); 686 return lldb::OptionValueSP(); 687 } 688 689 const Property * 690 OptionValueProperties::GetPropertyAtPath (const ExecutionContext *exe_ctx, 691 bool will_modify, 692 const char *name) const 693 { 694 const Property *property = nullptr; 695 if (name && name[0]) 696 { 697 const char *sub_name = nullptr; 698 ConstString key; 699 size_t key_len = ::strcspn (name, ".[{"); 700 701 if (name[key_len]) 702 { 703 key.SetCStringWithLength (name, key_len); 704 sub_name = name + key_len; 705 } 706 else 707 key.SetCString (name); 708 709 property = GetProperty (exe_ctx, will_modify, key); 710 if (sub_name && property) 711 { 712 if (sub_name[0] == '.') 713 { 714 OptionValueProperties *sub_properties = property->GetValue()->GetAsProperties(); 715 if (sub_properties) 716 return sub_properties->GetPropertyAtPath(exe_ctx, will_modify, sub_name + 1); 717 } 718 property = nullptr; 719 } 720 } 721 return property; 722 } 723 724 void 725 OptionValueProperties::DumpAllDescriptions (CommandInterpreter &interpreter, 726 Stream &strm) const 727 { 728 size_t max_name_len = 0; 729 const size_t num_properties = m_properties.size(); 730 for (size_t i=0; i<num_properties; ++i) 731 { 732 const Property *property = ProtectedGetPropertyAtIndex(i); 733 if (property) 734 max_name_len = std::max<size_t>(property->GetName().GetLength(), max_name_len); 735 } 736 for (size_t i=0; i<num_properties; ++i) 737 { 738 const Property *property = ProtectedGetPropertyAtIndex(i); 739 if (property) 740 property->DumpDescription (interpreter, strm, max_name_len, false); 741 } 742 } 743 744 void 745 OptionValueProperties::Apropos (const char *keyword, std::vector<const Property *> &matching_properties) const 746 { 747 const size_t num_properties = m_properties.size(); 748 StreamString strm; 749 for (size_t i=0; i<num_properties; ++i) 750 { 751 const Property *property = ProtectedGetPropertyAtIndex(i); 752 if (property) 753 { 754 const OptionValueProperties *properties = property->GetValue()->GetAsProperties(); 755 if (properties) 756 { 757 properties->Apropos (keyword, matching_properties); 758 } 759 else 760 { 761 bool match = false; 762 const char *name = property->GetName().GetCString(); 763 if (name && ::strcasestr(name, keyword)) 764 match = true; 765 else 766 { 767 const char *desc = property->GetDescription(); 768 if (desc && ::strcasestr(desc, keyword)) 769 match = true; 770 } 771 if (match) 772 { 773 matching_properties.push_back (property); 774 } 775 } 776 } 777 } 778 } 779 780 lldb::OptionValuePropertiesSP 781 OptionValueProperties::GetSubProperty (const ExecutionContext *exe_ctx, 782 const ConstString &name) 783 { 784 lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name, false)); 785 if (option_value_sp) 786 { 787 OptionValueProperties *ov_properties = option_value_sp->GetAsProperties (); 788 if (ov_properties) 789 return ov_properties->shared_from_this(); 790 } 791 return lldb::OptionValuePropertiesSP(); 792 } 793 794 795 796