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