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