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 24using namespace lldb; 25using namespace lldb_private; 26 27 28OptionValueProperties::OptionValueProperties (const ConstString &name) : 29 OptionValue (), 30 m_name (name), 31 m_properties (), 32 m_name_to_index () 33{ 34} 35 36OptionValueProperties::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 61size_t 62OptionValueProperties::GetNumProperties() const 63{ 64 return m_properties.size(); 65} 66 67 68void 69OptionValueProperties::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 82void 83OptionValueProperties::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// 116lldb::OptionValueSP 117OptionValueProperties::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 128lldb::OptionValueSP 129OptionValueProperties::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 208Error 209OptionValueProperties::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 228ConstString 229OptionValueProperties::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 238const char * 239OptionValueProperties::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 247uint32_t 248OptionValueProperties::GetPropertyIndex (const ConstString &name) const 249{ 250 return m_name_to_index.Find (name.GetCString(), SIZE_MAX); 251} 252 253const Property * 254OptionValueProperties::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 259const Property * 260OptionValueProperties::GetPropertyAtIndex (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const 261{ 262 return ProtectedGetPropertyAtIndex (idx); 263} 264 265lldb::OptionValueSP 266OptionValueProperties::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 276OptionValuePathMappings * 277OptionValueProperties::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 285OptionValueFileSpecList * 286OptionValueProperties::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 294OptionValueArch * 295OptionValueProperties::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 303bool 304OptionValueProperties::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 326bool 327OptionValueProperties::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 349bool 350OptionValueProperties::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 362bool 363OptionValueProperties::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 378OptionValueDictionary * 379OptionValueProperties::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 387int64_t 388OptionValueProperties::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 400bool 401OptionValueProperties::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 414OptionValueFileSpec * 415OptionValueProperties::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 428FileSpec 429OptionValueProperties::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 442bool 443OptionValueProperties::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 455const RegularExpression * 456OptionValueProperties::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 468OptionValueSInt64 * 469OptionValueProperties::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 481int64_t 482OptionValueProperties::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 494bool 495OptionValueProperties::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 507const char * 508OptionValueProperties::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 520bool 521OptionValueProperties::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 533OptionValueString * 534OptionValueProperties::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 543uint64_t 544OptionValueProperties::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 556bool 557OptionValueProperties::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 569bool 570OptionValueProperties::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 579Error 580OptionValueProperties::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 606void 607OptionValueProperties::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 627Error 628OptionValueProperties::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 650lldb::OptionValueSP 651OptionValueProperties::DeepCopy () const 652{ 653 assert(!"this shouldn't happen"); 654} 655 656const Property * 657OptionValueProperties::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 691void 692OptionValueProperties::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 711void 712OptionValueProperties::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 747lldb::OptionValuePropertiesSP 748OptionValueProperties::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