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 uint64_t 530 OptionValueProperties::GetPropertyAtIndexAsUInt64 (const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const 531 { 532 const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); 533 if (property) 534 { 535 OptionValue *value = property->GetValue().get(); 536 if (value) 537 return value->GetUInt64Value(fail_value); 538 } 539 return fail_value; 540 } 541 542 bool 543 OptionValueProperties::SetPropertyAtIndexAsUInt64 (const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value) 544 { 545 const Property *property = GetPropertyAtIndex (exe_ctx, true, idx); 546 if (property) 547 { 548 OptionValue *value = property->GetValue().get(); 549 if (value) 550 return value->SetUInt64Value(new_value); 551 } 552 return false; 553 } 554 555 bool 556 OptionValueProperties::Clear () 557 { 558 const size_t num_properties = m_properties.size(); 559 for (size_t i=0; i<num_properties; ++i) 560 m_properties[i].GetValue()->Clear(); 561 return true; 562 } 563 564 565 Error 566 OptionValueProperties::SetValueFromCString (const char *value, VarSetOperationType op) 567 { 568 Error error; 569 570 // Args args(value_cstr); 571 // const size_t argc = args.GetArgumentCount(); 572 switch (op) 573 { 574 case eVarSetOperationClear: 575 Clear (); 576 break; 577 578 case eVarSetOperationReplace: 579 case eVarSetOperationAssign: 580 case eVarSetOperationRemove: 581 case eVarSetOperationInsertBefore: 582 case eVarSetOperationInsertAfter: 583 case eVarSetOperationAppend: 584 case eVarSetOperationInvalid: 585 error = OptionValue::SetValueFromCString (value, op); 586 break; 587 } 588 589 return error; 590 } 591 592 void 593 OptionValueProperties::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) 594 { 595 const size_t num_properties = m_properties.size(); 596 for (size_t i=0; i<num_properties; ++i) 597 { 598 const Property *property = GetPropertyAtIndex(exe_ctx, false, i); 599 if (property) 600 { 601 OptionValue *option_value = property->GetValue().get(); 602 assert (option_value); 603 const bool transparent_value = option_value->ValueIsTransparent (); 604 property->Dump (exe_ctx, 605 strm, 606 dump_mask); 607 if (!transparent_value) 608 strm.EOL(); 609 } 610 } 611 } 612 613 Error 614 OptionValueProperties::DumpPropertyValue (const ExecutionContext *exe_ctx, 615 Stream &strm, 616 const char *property_path, 617 uint32_t dump_mask) 618 { 619 Error error; 620 const bool will_modify = false; 621 lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, property_path, will_modify, error)); 622 if (value_sp) 623 { 624 if (!value_sp->ValueIsTransparent ()) 625 { 626 if (dump_mask & eDumpOptionName) 627 strm.PutCString (property_path); 628 if (dump_mask & ~eDumpOptionName) 629 strm.PutChar (' '); 630 } 631 value_sp->DumpValue (exe_ctx, strm, dump_mask); 632 } 633 return error; 634 } 635 636 lldb::OptionValueSP 637 OptionValueProperties::DeepCopy () const 638 { 639 assert(!"this shouldn't happen"); 640 } 641 642 const Property * 643 OptionValueProperties::GetPropertyAtPath (const ExecutionContext *exe_ctx, 644 bool will_modify, 645 const char *name) const 646 { 647 const Property *property = NULL; 648 if (name && name[0]) 649 { 650 const char *sub_name = NULL; 651 ConstString key; 652 size_t key_len = ::strcspn (name, ".[{"); 653 654 if (name[key_len]) 655 { 656 key.SetCStringWithLength (name, key_len); 657 sub_name = name + key_len; 658 } 659 else 660 key.SetCString (name); 661 662 property = GetProperty (exe_ctx, will_modify, key); 663 if (sub_name && property) 664 { 665 if (sub_name[0] == '.') 666 { 667 OptionValueProperties *sub_properties = property->GetValue()->GetAsProperties(); 668 if (sub_properties) 669 return sub_properties->GetPropertyAtPath(exe_ctx, will_modify, sub_name + 1); 670 } 671 property = NULL; 672 } 673 } 674 return property; 675 } 676 677 void 678 OptionValueProperties::DumpAllDescriptions (CommandInterpreter &interpreter, 679 Stream &strm) const 680 { 681 size_t max_name_len = 0; 682 const size_t num_properties = m_properties.size(); 683 for (size_t i=0; i<num_properties; ++i) 684 { 685 const Property *property = ProtectedGetPropertyAtIndex(i); 686 if (property) 687 max_name_len = std::max<size_t>(property->GetName().GetLength(), max_name_len); 688 } 689 for (size_t i=0; i<num_properties; ++i) 690 { 691 const Property *property = ProtectedGetPropertyAtIndex(i); 692 if (property) 693 property->DumpDescription (interpreter, strm, max_name_len, false); 694 } 695 } 696 697 void 698 OptionValueProperties::Apropos (const char *keyword, std::vector<const Property *> &matching_properties) const 699 { 700 const size_t num_properties = m_properties.size(); 701 StreamString strm; 702 for (size_t i=0; i<num_properties; ++i) 703 { 704 const Property *property = ProtectedGetPropertyAtIndex(i); 705 if (property) 706 { 707 const OptionValueProperties *properties = property->GetValue()->GetAsProperties(); 708 if (properties) 709 { 710 properties->Apropos (keyword, matching_properties); 711 } 712 else 713 { 714 bool match = false; 715 const char *name = property->GetName().GetCString(); 716 if (name && ::strcasestr(name, keyword)) 717 match = true; 718 else 719 { 720 const char *desc = property->GetDescription(); 721 if (desc && ::strcasestr(desc, keyword)) 722 match = true; 723 } 724 if (match) 725 { 726 matching_properties.push_back (property); 727 } 728 } 729 } 730 } 731 } 732 733 734