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().GetCString(), 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.GetCString(), 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.GetCString(), 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.GetCString(), 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(exe_ctx, will_modify, 245 m_name_to_index.Find(name.GetCString(), SIZE_MAX)); 246 } 247 248 const Property *OptionValueProperties::GetPropertyAtIndex( 249 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { 250 return ProtectedGetPropertyAtIndex(idx); 251 } 252 253 lldb::OptionValueSP OptionValueProperties::GetPropertyValueAtIndex( 254 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { 255 const Property *setting = GetPropertyAtIndex(exe_ctx, will_modify, idx); 256 if (setting) 257 return setting->GetValue(); 258 return OptionValueSP(); 259 } 260 261 OptionValuePathMappings * 262 OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings( 263 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { 264 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx)); 265 if (value_sp) 266 return value_sp->GetAsPathMappings(); 267 return nullptr; 268 } 269 270 OptionValueFileSpecList * 271 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList( 272 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { 273 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx)); 274 if (value_sp) 275 return value_sp->GetAsFileSpecList(); 276 return nullptr; 277 } 278 279 OptionValueArch *OptionValueProperties::GetPropertyAtIndexAsOptionValueArch( 280 const ExecutionContext *exe_ctx, uint32_t idx) const { 281 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 282 if (property) 283 return property->GetValue()->GetAsArch(); 284 return nullptr; 285 } 286 287 OptionValueLanguage * 288 OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage( 289 const ExecutionContext *exe_ctx, uint32_t idx) const { 290 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 291 if (property) 292 return property->GetValue()->GetAsLanguage(); 293 return nullptr; 294 } 295 296 bool OptionValueProperties::GetPropertyAtIndexAsArgs( 297 const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const { 298 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 299 if (property) { 300 OptionValue *value = property->GetValue().get(); 301 if (value) { 302 const OptionValueArray *array = value->GetAsArray(); 303 if (array) 304 return array->GetArgs(args); 305 else { 306 const OptionValueDictionary *dict = value->GetAsDictionary(); 307 if (dict) 308 return dict->GetArgs(args); 309 } 310 } 311 } 312 return false; 313 } 314 315 bool OptionValueProperties::SetPropertyAtIndexFromArgs( 316 const ExecutionContext *exe_ctx, uint32_t idx, const Args &args) { 317 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); 318 if (property) { 319 OptionValue *value = property->GetValue().get(); 320 if (value) { 321 OptionValueArray *array = value->GetAsArray(); 322 if (array) 323 return array->SetArgs(args, eVarSetOperationAssign).Success(); 324 else { 325 OptionValueDictionary *dict = value->GetAsDictionary(); 326 if (dict) 327 return dict->SetArgs(args, eVarSetOperationAssign).Success(); 328 } 329 } 330 } 331 return false; 332 } 333 334 bool OptionValueProperties::GetPropertyAtIndexAsBoolean( 335 const ExecutionContext *exe_ctx, uint32_t idx, bool fail_value) const { 336 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 337 if (property) { 338 OptionValue *value = property->GetValue().get(); 339 if (value) 340 return value->GetBooleanValue(fail_value); 341 } 342 return fail_value; 343 } 344 345 bool OptionValueProperties::SetPropertyAtIndexAsBoolean( 346 const ExecutionContext *exe_ctx, uint32_t idx, bool new_value) { 347 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); 348 if (property) { 349 OptionValue *value = property->GetValue().get(); 350 if (value) { 351 value->SetBooleanValue(new_value); 352 return true; 353 } 354 } 355 return false; 356 } 357 358 OptionValueDictionary * 359 OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary( 360 const ExecutionContext *exe_ctx, uint32_t idx) const { 361 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 362 if (property) 363 return property->GetValue()->GetAsDictionary(); 364 return nullptr; 365 } 366 367 int64_t OptionValueProperties::GetPropertyAtIndexAsEnumeration( 368 const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const { 369 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 370 if (property) { 371 OptionValue *value = property->GetValue().get(); 372 if (value) 373 return value->GetEnumerationValue(fail_value); 374 } 375 return fail_value; 376 } 377 378 bool OptionValueProperties::SetPropertyAtIndexAsEnumeration( 379 const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) { 380 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); 381 if (property) { 382 OptionValue *value = property->GetValue().get(); 383 if (value) 384 return value->SetEnumerationValue(new_value); 385 } 386 return false; 387 } 388 389 const FormatEntity::Entry * 390 OptionValueProperties::GetPropertyAtIndexAsFormatEntity( 391 const ExecutionContext *exe_ctx, uint32_t idx) { 392 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); 393 if (property) { 394 OptionValue *value = property->GetValue().get(); 395 if (value) 396 return value->GetFormatEntity(); 397 } 398 return nullptr; 399 } 400 401 OptionValueFileSpec * 402 OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec( 403 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { 404 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 405 if (property) { 406 OptionValue *value = property->GetValue().get(); 407 if (value) 408 return value->GetAsFileSpec(); 409 } 410 return nullptr; 411 } 412 413 FileSpec OptionValueProperties::GetPropertyAtIndexAsFileSpec( 414 const ExecutionContext *exe_ctx, uint32_t idx) const { 415 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 416 if (property) { 417 OptionValue *value = property->GetValue().get(); 418 if (value) 419 return value->GetFileSpecValue(); 420 } 421 return FileSpec(); 422 } 423 424 bool OptionValueProperties::SetPropertyAtIndexAsFileSpec( 425 const ExecutionContext *exe_ctx, uint32_t idx, 426 const FileSpec &new_file_spec) { 427 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); 428 if (property) { 429 OptionValue *value = property->GetValue().get(); 430 if (value) 431 return value->SetFileSpecValue(new_file_spec); 432 } 433 return false; 434 } 435 436 const RegularExpression * 437 OptionValueProperties::GetPropertyAtIndexAsOptionValueRegex( 438 const ExecutionContext *exe_ctx, uint32_t idx) const { 439 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 440 if (property) { 441 OptionValue *value = property->GetValue().get(); 442 if (value) 443 return value->GetRegexValue(); 444 } 445 return nullptr; 446 } 447 448 OptionValueSInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64( 449 const ExecutionContext *exe_ctx, uint32_t idx) const { 450 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 451 if (property) { 452 OptionValue *value = property->GetValue().get(); 453 if (value) 454 return value->GetAsSInt64(); 455 } 456 return nullptr; 457 } 458 459 int64_t OptionValueProperties::GetPropertyAtIndexAsSInt64( 460 const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const { 461 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 462 if (property) { 463 OptionValue *value = property->GetValue().get(); 464 if (value) 465 return value->GetSInt64Value(fail_value); 466 } 467 return fail_value; 468 } 469 470 bool OptionValueProperties::SetPropertyAtIndexAsSInt64( 471 const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) { 472 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); 473 if (property) { 474 OptionValue *value = property->GetValue().get(); 475 if (value) 476 return value->SetSInt64Value(new_value); 477 } 478 return false; 479 } 480 481 const char *OptionValueProperties::GetPropertyAtIndexAsString( 482 const ExecutionContext *exe_ctx, uint32_t idx, 483 const char *fail_value) const { 484 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 485 if (property) { 486 OptionValue *value = property->GetValue().get(); 487 if (value) 488 return value->GetStringValue(fail_value); 489 } 490 return fail_value; 491 } 492 493 bool OptionValueProperties::SetPropertyAtIndexAsString( 494 const ExecutionContext *exe_ctx, uint32_t idx, llvm::StringRef new_value) { 495 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); 496 if (property) { 497 OptionValue *value = property->GetValue().get(); 498 if (value) 499 return value->SetStringValue(new_value); 500 } 501 return false; 502 } 503 504 OptionValueString *OptionValueProperties::GetPropertyAtIndexAsOptionValueString( 505 const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const { 506 OptionValueSP value_sp(GetPropertyValueAtIndex(exe_ctx, will_modify, idx)); 507 if (value_sp) 508 return value_sp->GetAsString(); 509 return nullptr; 510 } 511 512 uint64_t OptionValueProperties::GetPropertyAtIndexAsUInt64( 513 const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const { 514 const Property *property = GetPropertyAtIndex(exe_ctx, false, idx); 515 if (property) { 516 OptionValue *value = property->GetValue().get(); 517 if (value) 518 return value->GetUInt64Value(fail_value); 519 } 520 return fail_value; 521 } 522 523 bool OptionValueProperties::SetPropertyAtIndexAsUInt64( 524 const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value) { 525 const Property *property = GetPropertyAtIndex(exe_ctx, true, idx); 526 if (property) { 527 OptionValue *value = property->GetValue().get(); 528 if (value) 529 return value->SetUInt64Value(new_value); 530 } 531 return false; 532 } 533 534 bool OptionValueProperties::Clear() { 535 const size_t num_properties = m_properties.size(); 536 for (size_t i = 0; i < num_properties; ++i) 537 m_properties[i].GetValue()->Clear(); 538 return true; 539 } 540 541 Error OptionValueProperties::SetValueFromString(llvm::StringRef value, 542 VarSetOperationType op) { 543 Error error; 544 545 // Args args(value_cstr); 546 // const size_t argc = args.GetArgumentCount(); 547 switch (op) { 548 case eVarSetOperationClear: 549 Clear(); 550 break; 551 552 case eVarSetOperationReplace: 553 case eVarSetOperationAssign: 554 case eVarSetOperationRemove: 555 case eVarSetOperationInsertBefore: 556 case eVarSetOperationInsertAfter: 557 case eVarSetOperationAppend: 558 case eVarSetOperationInvalid: 559 error = OptionValue::SetValueFromString(value, op); 560 break; 561 } 562 563 return error; 564 } 565 566 void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx, 567 Stream &strm, uint32_t dump_mask) { 568 const size_t num_properties = m_properties.size(); 569 for (size_t i = 0; i < num_properties; ++i) { 570 const Property *property = GetPropertyAtIndex(exe_ctx, false, i); 571 if (property) { 572 OptionValue *option_value = property->GetValue().get(); 573 assert(option_value); 574 const bool transparent_value = option_value->ValueIsTransparent(); 575 property->Dump(exe_ctx, strm, dump_mask); 576 if (!transparent_value) 577 strm.EOL(); 578 } 579 } 580 } 581 582 Error OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx, 583 Stream &strm, 584 const char *property_path, 585 uint32_t dump_mask) { 586 Error error; 587 const bool will_modify = false; 588 lldb::OptionValueSP value_sp( 589 GetSubValue(exe_ctx, property_path, will_modify, error)); 590 if (value_sp) { 591 if (!value_sp->ValueIsTransparent()) { 592 if (dump_mask & eDumpOptionName) 593 strm.PutCString(property_path); 594 if (dump_mask & ~eDumpOptionName) 595 strm.PutChar(' '); 596 } 597 value_sp->DumpValue(exe_ctx, strm, dump_mask); 598 } 599 return error; 600 } 601 602 lldb::OptionValueSP OptionValueProperties::DeepCopy() const { 603 assert(!"this shouldn't happen"); 604 return lldb::OptionValueSP(); 605 } 606 607 const Property *OptionValueProperties::GetPropertyAtPath( 608 const ExecutionContext *exe_ctx, bool will_modify, const char *name) const { 609 const Property *property = nullptr; 610 if (name && name[0]) { 611 const char *sub_name = nullptr; 612 ConstString key; 613 size_t key_len = ::strcspn(name, ".[{"); 614 615 if (name[key_len]) { 616 key.SetCStringWithLength(name, key_len); 617 sub_name = name + key_len; 618 } else 619 key.SetCString(name); 620 621 property = GetProperty(exe_ctx, will_modify, key); 622 if (sub_name && property) { 623 if (sub_name[0] == '.') { 624 OptionValueProperties *sub_properties = 625 property->GetValue()->GetAsProperties(); 626 if (sub_properties) 627 return sub_properties->GetPropertyAtPath(exe_ctx, will_modify, 628 sub_name + 1); 629 } 630 property = nullptr; 631 } 632 } 633 return property; 634 } 635 636 void OptionValueProperties::DumpAllDescriptions(CommandInterpreter &interpreter, 637 Stream &strm) const { 638 size_t max_name_len = 0; 639 const size_t num_properties = m_properties.size(); 640 for (size_t i = 0; i < num_properties; ++i) { 641 const Property *property = ProtectedGetPropertyAtIndex(i); 642 if (property) 643 max_name_len = 644 std::max<size_t>(property->GetName().GetLength(), max_name_len); 645 } 646 for (size_t i = 0; i < num_properties; ++i) { 647 const Property *property = ProtectedGetPropertyAtIndex(i); 648 if (property) 649 property->DumpDescription(interpreter, strm, max_name_len, false); 650 } 651 } 652 653 void OptionValueProperties::Apropos( 654 const char *keyword, 655 std::vector<const Property *> &matching_properties) const { 656 const size_t num_properties = m_properties.size(); 657 StreamString strm; 658 for (size_t i = 0; i < num_properties; ++i) { 659 const Property *property = ProtectedGetPropertyAtIndex(i); 660 if (property) { 661 const OptionValueProperties *properties = 662 property->GetValue()->GetAsProperties(); 663 if (properties) { 664 properties->Apropos(keyword, matching_properties); 665 } else { 666 bool match = false; 667 const char *name = property->GetName().GetCString(); 668 if (name && ::strcasestr(name, keyword)) 669 match = true; 670 else { 671 const char *desc = property->GetDescription(); 672 if (desc && ::strcasestr(desc, keyword)) 673 match = true; 674 } 675 if (match) { 676 matching_properties.push_back(property); 677 } 678 } 679 } 680 } 681 } 682 683 lldb::OptionValuePropertiesSP 684 OptionValueProperties::GetSubProperty(const ExecutionContext *exe_ctx, 685 const ConstString &name) { 686 lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name, false)); 687 if (option_value_sp) { 688 OptionValueProperties *ov_properties = option_value_sp->GetAsProperties(); 689 if (ov_properties) 690 return ov_properties->shared_from_this(); 691 } 692 return lldb::OptionValuePropertiesSP(); 693 } 694