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