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