1254721Semaste//===-- Variable.cpp --------------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/Symbol/Variable.h" 11254721Semaste 12254721Semaste#include "lldb/Core/Module.h" 13254721Semaste#include "lldb/Core/Stream.h" 14254721Semaste#include "lldb/Core/RegularExpression.h" 15254721Semaste#include "lldb/Core/ValueObject.h" 16254721Semaste#include "lldb/Core/ValueObjectVariable.h" 17254721Semaste#include "lldb/Symbol/Block.h" 18254721Semaste#include "lldb/Symbol/Function.h" 19254721Semaste#include "lldb/Symbol/SymbolContext.h" 20254721Semaste#include "lldb/Symbol/Type.h" 21254721Semaste#include "lldb/Symbol/VariableList.h" 22254721Semaste#include "lldb/Target/ABI.h" 23254721Semaste#include "lldb/Target/Process.h" 24254721Semaste#include "lldb/Target/RegisterContext.h" 25254721Semaste#include "lldb/Target/StackFrame.h" 26254721Semaste#include "lldb/Target/Thread.h" 27254721Semaste#include "lldb/Target/Target.h" 28254721Semaste 29254721Semasteusing namespace lldb; 30254721Semasteusing namespace lldb_private; 31254721Semaste 32254721Semaste//---------------------------------------------------------------------- 33254721Semaste// Variable constructor 34254721Semaste//---------------------------------------------------------------------- 35254721SemasteVariable::Variable 36254721Semaste( 37254721Semaste lldb::user_id_t uid, 38254721Semaste const char *name, 39254721Semaste const char *mangled, // The mangled variable name for variables in namespaces 40254721Semaste const lldb::SymbolFileTypeSP &symfile_type_sp, 41254721Semaste ValueType scope, 42254721Semaste SymbolContextScope *context, 43254721Semaste Declaration* decl_ptr, 44254721Semaste const DWARFExpression& location, 45254721Semaste bool external, 46254721Semaste bool artificial 47254721Semaste) : 48254721Semaste UserID(uid), 49254721Semaste m_name(name), 50254721Semaste m_mangled (ConstString(mangled), true), 51254721Semaste m_symfile_type_sp(symfile_type_sp), 52254721Semaste m_scope(scope), 53254721Semaste m_owner_scope(context), 54254721Semaste m_declaration(decl_ptr), 55254721Semaste m_location(location), 56254721Semaste m_external(external), 57254721Semaste m_artificial(artificial) 58254721Semaste{ 59254721Semaste} 60254721Semaste 61254721Semaste//---------------------------------------------------------------------- 62254721Semaste// Destructor 63254721Semaste//---------------------------------------------------------------------- 64254721SemasteVariable::~Variable() 65254721Semaste{ 66254721Semaste} 67254721Semaste 68254721Semaste 69254721Semasteconst ConstString& 70254721SemasteVariable::GetName() const 71254721Semaste{ 72254721Semaste if (m_mangled) 73254721Semaste return m_mangled.GetName(); 74254721Semaste return m_name; 75254721Semaste} 76254721Semaste 77254721Semastebool 78254721SemasteVariable::NameMatches (const RegularExpression& regex) const 79254721Semaste{ 80254721Semaste if (regex.Execute (m_name.AsCString())) 81254721Semaste return true; 82254721Semaste return m_mangled.NameMatches (regex); 83254721Semaste} 84254721Semaste 85254721SemasteType * 86254721SemasteVariable::GetType() 87254721Semaste{ 88254721Semaste if (m_symfile_type_sp) 89254721Semaste return m_symfile_type_sp->GetType(); 90254721Semaste return NULL; 91254721Semaste} 92254721Semaste 93254721Semastevoid 94254721SemasteVariable::Dump(Stream *s, bool show_context) const 95254721Semaste{ 96254721Semaste s->Printf("%p: ", this); 97254721Semaste s->Indent(); 98254721Semaste *s << "Variable" << (const UserID&)*this; 99254721Semaste 100254721Semaste if (m_name) 101254721Semaste *s << ", name = \"" << m_name << "\""; 102254721Semaste 103254721Semaste if (m_symfile_type_sp) 104254721Semaste { 105254721Semaste Type *type = m_symfile_type_sp->GetType(); 106254721Semaste if (type) 107254721Semaste { 108254721Semaste *s << ", type = {" << type->GetID() << "} " << (void*)type << " ("; 109254721Semaste type->DumpTypeName(s); 110254721Semaste s->PutChar(')'); 111254721Semaste } 112254721Semaste } 113254721Semaste 114254721Semaste if (m_scope != eValueTypeInvalid) 115254721Semaste { 116254721Semaste s->PutCString(", scope = "); 117254721Semaste switch (m_scope) 118254721Semaste { 119254721Semaste case eValueTypeVariableGlobal: s->PutCString(m_external ? "global" : "static"); break; 120254721Semaste case eValueTypeVariableArgument: s->PutCString("parameter"); break; 121254721Semaste case eValueTypeVariableLocal: s->PutCString("local"); break; 122254721Semaste default: *s << "??? (" << m_scope << ')'; 123254721Semaste } 124254721Semaste } 125254721Semaste 126254721Semaste if (show_context && m_owner_scope != NULL) 127254721Semaste { 128254721Semaste s->PutCString(", context = ( "); 129254721Semaste m_owner_scope->DumpSymbolContext(s); 130254721Semaste s->PutCString(" )"); 131254721Semaste } 132254721Semaste 133254721Semaste bool show_fullpaths = false; 134254721Semaste m_declaration.Dump(s, show_fullpaths); 135254721Semaste 136254721Semaste if (m_location.IsValid()) 137254721Semaste { 138254721Semaste s->PutCString(", location = "); 139254721Semaste lldb::addr_t loclist_base_addr = LLDB_INVALID_ADDRESS; 140254721Semaste if (m_location.IsLocationList()) 141254721Semaste { 142254721Semaste SymbolContext variable_sc; 143254721Semaste m_owner_scope->CalculateSymbolContext(&variable_sc); 144254721Semaste if (variable_sc.function) 145254721Semaste loclist_base_addr = variable_sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); 146254721Semaste } 147254721Semaste ABI *abi = NULL; 148254721Semaste if (m_owner_scope) 149254721Semaste { 150254721Semaste ModuleSP module_sp (m_owner_scope->CalculateSymbolContextModule()); 151254721Semaste if (module_sp) 152254721Semaste abi = ABI::FindPlugin (module_sp->GetArchitecture()).get(); 153254721Semaste } 154254721Semaste m_location.GetDescription(s, lldb::eDescriptionLevelBrief, loclist_base_addr, abi); 155254721Semaste } 156254721Semaste 157254721Semaste if (m_external) 158254721Semaste s->PutCString(", external"); 159254721Semaste 160254721Semaste if (m_artificial) 161254721Semaste s->PutCString(", artificial"); 162254721Semaste 163254721Semaste s->EOL(); 164254721Semaste} 165254721Semaste 166254721Semastebool 167254721SemasteVariable::DumpDeclaration (Stream *s, bool show_fullpaths, bool show_module) 168254721Semaste{ 169254721Semaste bool dumped_declaration_info = false; 170254721Semaste if (m_owner_scope) 171254721Semaste { 172254721Semaste SymbolContext sc; 173254721Semaste m_owner_scope->CalculateSymbolContext(&sc); 174254721Semaste sc.block = NULL; 175254721Semaste sc.line_entry.Clear(); 176254721Semaste bool show_inlined_frames = false; 177254721Semaste 178254721Semaste dumped_declaration_info = sc.DumpStopContext (s, 179254721Semaste NULL, 180254721Semaste Address(), 181254721Semaste show_fullpaths, 182254721Semaste show_module, 183254721Semaste show_inlined_frames); 184254721Semaste 185254721Semaste if (sc.function) 186254721Semaste s->PutChar(':'); 187254721Semaste } 188254721Semaste if (m_declaration.DumpStopContext (s, false)) 189254721Semaste dumped_declaration_info = true; 190254721Semaste return dumped_declaration_info; 191254721Semaste} 192254721Semaste 193254721Semastesize_t 194254721SemasteVariable::MemorySize() const 195254721Semaste{ 196254721Semaste return sizeof(Variable); 197254721Semaste} 198254721Semaste 199254721Semaste 200254721Semastevoid 201254721SemasteVariable::CalculateSymbolContext (SymbolContext *sc) 202254721Semaste{ 203254721Semaste if (m_owner_scope) 204254721Semaste m_owner_scope->CalculateSymbolContext(sc); 205254721Semaste else 206254721Semaste sc->Clear(false); 207254721Semaste} 208254721Semaste 209254721Semastebool 210254721SemasteVariable::LocationIsValidForFrame (StackFrame *frame) 211254721Semaste{ 212254721Semaste // Is the variable is described by a single location? 213254721Semaste if (!m_location.IsLocationList()) 214254721Semaste { 215254721Semaste // Yes it is, the location is valid. 216254721Semaste return true; 217254721Semaste } 218254721Semaste 219254721Semaste if (frame) 220254721Semaste { 221254721Semaste Function *function = frame->GetSymbolContext(eSymbolContextFunction).function; 222254721Semaste if (function) 223254721Semaste { 224254721Semaste TargetSP target_sp (frame->CalculateTarget()); 225254721Semaste 226254721Semaste addr_t loclist_base_load_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress (target_sp.get()); 227254721Semaste if (loclist_base_load_addr == LLDB_INVALID_ADDRESS) 228254721Semaste return false; 229254721Semaste // It is a location list. We just need to tell if the location 230254721Semaste // list contains the current address when converted to a load 231254721Semaste // address 232254721Semaste return m_location.LocationListContainsAddress (loclist_base_load_addr, 233254721Semaste frame->GetFrameCodeAddress().GetLoadAddress (target_sp.get())); 234254721Semaste } 235254721Semaste } 236254721Semaste return false; 237254721Semaste} 238254721Semaste 239254721Semastebool 240254721SemasteVariable::LocationIsValidForAddress (const Address &address) 241254721Semaste{ 242254721Semaste // Be sure to resolve the address to section offset prior to 243254721Semaste // calling this function. 244254721Semaste if (address.IsSectionOffset()) 245254721Semaste { 246254721Semaste SymbolContext sc; 247254721Semaste CalculateSymbolContext(&sc); 248254721Semaste if (sc.module_sp == address.GetModule()) 249254721Semaste { 250254721Semaste // Is the variable is described by a single location? 251254721Semaste if (!m_location.IsLocationList()) 252254721Semaste { 253254721Semaste // Yes it is, the location is valid. 254254721Semaste return true; 255254721Semaste } 256254721Semaste 257254721Semaste if (sc.function) 258254721Semaste { 259254721Semaste addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); 260254721Semaste if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) 261254721Semaste return false; 262254721Semaste // It is a location list. We just need to tell if the location 263254721Semaste // list contains the current address when converted to a load 264254721Semaste // address 265254721Semaste return m_location.LocationListContainsAddress (loclist_base_file_addr, 266254721Semaste address.GetFileAddress()); 267254721Semaste } 268254721Semaste } 269254721Semaste } 270254721Semaste return false; 271254721Semaste} 272254721Semaste 273254721Semastebool 274254721SemasteVariable::IsInScope (StackFrame *frame) 275254721Semaste{ 276254721Semaste switch (m_scope) 277254721Semaste { 278254721Semaste case eValueTypeRegister: 279254721Semaste case eValueTypeRegisterSet: 280254721Semaste return frame != NULL; 281254721Semaste 282254721Semaste case eValueTypeConstResult: 283254721Semaste case eValueTypeVariableGlobal: 284254721Semaste case eValueTypeVariableStatic: 285254721Semaste return true; 286254721Semaste 287254721Semaste case eValueTypeVariableArgument: 288254721Semaste case eValueTypeVariableLocal: 289254721Semaste if (frame) 290254721Semaste { 291254721Semaste // We don't have a location list, we just need to see if the block 292254721Semaste // that this variable was defined in is currently 293254721Semaste Block *deepest_frame_block = frame->GetSymbolContext(eSymbolContextBlock).block; 294254721Semaste if (deepest_frame_block) 295254721Semaste { 296254721Semaste SymbolContext variable_sc; 297254721Semaste CalculateSymbolContext (&variable_sc); 298254721Semaste // Check for static or global variable defined at the compile unit 299254721Semaste // level that wasn't defined in a block 300254721Semaste if (variable_sc.block == NULL) 301254721Semaste return true; 302254721Semaste 303254721Semaste if (variable_sc.block == deepest_frame_block) 304254721Semaste return true; 305254721Semaste return variable_sc.block->Contains (deepest_frame_block); 306254721Semaste } 307254721Semaste } 308254721Semaste break; 309254721Semaste 310254721Semaste default: 311254721Semaste break; 312254721Semaste } 313254721Semaste return false; 314254721Semaste} 315254721Semaste 316254721SemasteError 317254721SemasteVariable::GetValuesForVariableExpressionPath (const char *variable_expr_path, 318254721Semaste ExecutionContextScope *scope, 319254721Semaste GetVariableCallback callback, 320254721Semaste void *baton, 321254721Semaste VariableList &variable_list, 322254721Semaste ValueObjectList &valobj_list) 323254721Semaste{ 324254721Semaste Error error; 325254721Semaste if (variable_expr_path && callback) 326254721Semaste { 327254721Semaste switch (variable_expr_path[0]) 328254721Semaste { 329254721Semaste case '*': 330254721Semaste { 331254721Semaste error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1, 332254721Semaste scope, 333254721Semaste callback, 334254721Semaste baton, 335254721Semaste variable_list, 336254721Semaste valobj_list); 337254721Semaste if (error.Success()) 338254721Semaste { 339254721Semaste for (uint32_t i=0; i<valobj_list.GetSize(); ) 340254721Semaste { 341254721Semaste Error tmp_error; 342254721Semaste ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->Dereference(tmp_error)); 343254721Semaste if (tmp_error.Fail()) 344254721Semaste { 345254721Semaste variable_list.RemoveVariableAtIndex (i); 346254721Semaste valobj_list.RemoveValueObjectAtIndex (i); 347254721Semaste } 348254721Semaste else 349254721Semaste { 350254721Semaste valobj_list.SetValueObjectAtIndex (i, valobj_sp); 351254721Semaste ++i; 352254721Semaste } 353254721Semaste } 354254721Semaste } 355254721Semaste else 356254721Semaste { 357254721Semaste error.SetErrorString ("unknown error"); 358254721Semaste } 359254721Semaste return error; 360254721Semaste } 361254721Semaste break; 362254721Semaste 363254721Semaste case '&': 364254721Semaste { 365254721Semaste error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1, 366254721Semaste scope, 367254721Semaste callback, 368254721Semaste baton, 369254721Semaste variable_list, 370254721Semaste valobj_list); 371254721Semaste if (error.Success()) 372254721Semaste { 373254721Semaste for (uint32_t i=0; i<valobj_list.GetSize(); ) 374254721Semaste { 375254721Semaste Error tmp_error; 376254721Semaste ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->AddressOf(tmp_error)); 377254721Semaste if (tmp_error.Fail()) 378254721Semaste { 379254721Semaste variable_list.RemoveVariableAtIndex (i); 380254721Semaste valobj_list.RemoveValueObjectAtIndex (i); 381254721Semaste } 382254721Semaste else 383254721Semaste { 384254721Semaste valobj_list.SetValueObjectAtIndex (i, valobj_sp); 385254721Semaste ++i; 386254721Semaste } 387254721Semaste } 388254721Semaste } 389254721Semaste else 390254721Semaste { 391254721Semaste error.SetErrorString ("unknown error"); 392254721Semaste } 393254721Semaste return error; 394254721Semaste } 395254721Semaste break; 396254721Semaste 397254721Semaste default: 398254721Semaste { 399254721Semaste static RegularExpression g_regex ("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)"); 400254721Semaste RegularExpression::Match regex_match(1); 401254721Semaste if (g_regex.Execute(variable_expr_path, ®ex_match)) 402254721Semaste { 403254721Semaste std::string variable_name; 404254721Semaste if (regex_match.GetMatchAtIndex(variable_expr_path, 1, variable_name)) 405254721Semaste { 406254721Semaste variable_list.Clear(); 407254721Semaste if (callback (baton, variable_name.c_str(), variable_list)) 408254721Semaste { 409254721Semaste uint32_t i=0; 410254721Semaste while (i < variable_list.GetSize()) 411254721Semaste { 412254721Semaste VariableSP var_sp (variable_list.GetVariableAtIndex (i)); 413254721Semaste ValueObjectSP valobj_sp; 414254721Semaste if (var_sp) 415254721Semaste { 416254721Semaste ValueObjectSP variable_valobj_sp(ValueObjectVariable::Create (scope, var_sp)); 417254721Semaste if (variable_valobj_sp) 418254721Semaste { 419254721Semaste const char *variable_sub_expr_path = variable_expr_path + variable_name.size(); 420254721Semaste if (*variable_sub_expr_path) 421254721Semaste { 422254721Semaste const char* first_unparsed = NULL; 423254721Semaste ValueObject::ExpressionPathScanEndReason reason_to_stop; 424254721Semaste ValueObject::ExpressionPathEndResultType final_value_type; 425254721Semaste ValueObject::GetValueForExpressionPathOptions options; 426254721Semaste ValueObject::ExpressionPathAftermath final_task_on_target; 427254721Semaste 428254721Semaste valobj_sp = variable_valobj_sp->GetValueForExpressionPath (variable_sub_expr_path, 429254721Semaste &first_unparsed, 430254721Semaste &reason_to_stop, 431254721Semaste &final_value_type, 432254721Semaste options, 433254721Semaste &final_task_on_target); 434254721Semaste if (!valobj_sp) 435254721Semaste { 436254721Semaste error.SetErrorStringWithFormat ("invalid expression path '%s' for variable '%s'", 437254721Semaste variable_sub_expr_path, 438254721Semaste var_sp->GetName().GetCString()); 439254721Semaste } 440254721Semaste } 441254721Semaste else 442254721Semaste { 443254721Semaste // Just the name of a variable with no extras 444254721Semaste valobj_sp = variable_valobj_sp; 445254721Semaste } 446254721Semaste } 447254721Semaste } 448254721Semaste 449254721Semaste if (!var_sp || !valobj_sp) 450254721Semaste { 451254721Semaste variable_list.RemoveVariableAtIndex (i); 452254721Semaste } 453254721Semaste else 454254721Semaste { 455254721Semaste valobj_list.Append(valobj_sp); 456254721Semaste ++i; 457254721Semaste } 458254721Semaste } 459254721Semaste 460254721Semaste if (variable_list.GetSize() > 0) 461254721Semaste { 462254721Semaste error.Clear(); 463254721Semaste return error; 464254721Semaste } 465254721Semaste } 466254721Semaste } 467254721Semaste } 468254721Semaste error.SetErrorStringWithFormat ("unable to extract a variable name from '%s'", variable_expr_path); 469254721Semaste } 470254721Semaste break; 471254721Semaste } 472254721Semaste } 473254721Semaste error.SetErrorString ("unknown error"); 474254721Semaste return error; 475254721Semaste} 476254721Semaste 477254721Semastebool 478254721SemasteVariable::DumpLocationForAddress (Stream *s, const Address &address) 479254721Semaste{ 480254721Semaste // Be sure to resolve the address to section offset prior to 481254721Semaste // calling this function. 482254721Semaste if (address.IsSectionOffset()) 483254721Semaste { 484254721Semaste SymbolContext sc; 485254721Semaste CalculateSymbolContext(&sc); 486254721Semaste if (sc.module_sp == address.GetModule()) 487254721Semaste { 488254721Semaste ABI *abi = NULL; 489254721Semaste if (m_owner_scope) 490254721Semaste { 491254721Semaste ModuleSP module_sp (m_owner_scope->CalculateSymbolContextModule()); 492254721Semaste if (module_sp) 493254721Semaste abi = ABI::FindPlugin (module_sp->GetArchitecture()).get(); 494254721Semaste } 495254721Semaste 496254721Semaste const addr_t file_addr = address.GetFileAddress(); 497254721Semaste if (sc.function) 498254721Semaste { 499254721Semaste if (sc.function->GetAddressRange().ContainsFileAddress(address)) 500254721Semaste { 501254721Semaste addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); 502254721Semaste if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) 503254721Semaste return false; 504254721Semaste return m_location.DumpLocationForAddress (s, 505254721Semaste eDescriptionLevelBrief, 506254721Semaste loclist_base_file_addr, 507254721Semaste file_addr, 508254721Semaste abi); 509254721Semaste } 510254721Semaste } 511254721Semaste return m_location.DumpLocationForAddress (s, 512254721Semaste eDescriptionLevelBrief, 513254721Semaste LLDB_INVALID_ADDRESS, 514254721Semaste file_addr, 515254721Semaste abi); 516254721Semaste } 517254721Semaste } 518254721Semaste return false; 519254721Semaste} 520254721Semaste 521254721Semaste 522254721Semastestatic void 523254721SemastePrivateAutoComplete (StackFrame *frame, 524254721Semaste const std::string &partial_path, 525254721Semaste const std::string &prefix_path, // Anything that has been resolved already will be in here 526254721Semaste const ClangASTType& clang_type, 527254721Semaste StringList &matches, 528254721Semaste bool &word_complete); 529254721Semaste 530254721Semastestatic void 531254721SemastePrivateAutoCompleteMembers (StackFrame *frame, 532254721Semaste const std::string &partial_member_name, 533254721Semaste const std::string &partial_path, 534254721Semaste const std::string &prefix_path, // Anything that has been resolved already will be in here 535254721Semaste const ClangASTType& clang_type, 536254721Semaste StringList &matches, 537254721Semaste bool &word_complete); 538254721Semaste 539254721Semastestatic void 540254721SemastePrivateAutoCompleteMembers (StackFrame *frame, 541254721Semaste const std::string &partial_member_name, 542254721Semaste const std::string &partial_path, 543254721Semaste const std::string &prefix_path, // Anything that has been resolved already will be in here 544254721Semaste const ClangASTType& clang_type, 545254721Semaste StringList &matches, 546254721Semaste bool &word_complete) 547254721Semaste{ 548254721Semaste 549254721Semaste // We are in a type parsing child members 550254721Semaste const uint32_t num_bases = clang_type.GetNumDirectBaseClasses(); 551254721Semaste 552254721Semaste if (num_bases > 0) 553254721Semaste { 554254721Semaste for (uint32_t i = 0; i < num_bases; ++i) 555254721Semaste { 556254721Semaste ClangASTType base_class_type (clang_type.GetDirectBaseClassAtIndex (i, NULL)); 557254721Semaste 558254721Semaste PrivateAutoCompleteMembers (frame, 559254721Semaste partial_member_name, 560254721Semaste partial_path, 561254721Semaste prefix_path, 562254721Semaste base_class_type.GetCanonicalType(), 563254721Semaste matches, 564254721Semaste word_complete); 565254721Semaste } 566254721Semaste } 567254721Semaste 568254721Semaste const uint32_t num_vbases = clang_type.GetNumVirtualBaseClasses(); 569254721Semaste 570254721Semaste if (num_vbases > 0) 571254721Semaste { 572254721Semaste for (uint32_t i = 0; i < num_vbases; ++i) 573254721Semaste { 574254721Semaste ClangASTType vbase_class_type (clang_type.GetVirtualBaseClassAtIndex(i,NULL)); 575254721Semaste 576254721Semaste PrivateAutoCompleteMembers (frame, 577254721Semaste partial_member_name, 578254721Semaste partial_path, 579254721Semaste prefix_path, 580254721Semaste vbase_class_type.GetCanonicalType(), 581254721Semaste matches, 582254721Semaste word_complete); 583254721Semaste } 584254721Semaste } 585254721Semaste 586254721Semaste // We are in a type parsing child members 587254721Semaste const uint32_t num_fields = clang_type.GetNumFields(); 588254721Semaste 589254721Semaste if (num_fields > 0) 590254721Semaste { 591254721Semaste for (uint32_t i = 0; i < num_fields; ++i) 592254721Semaste { 593254721Semaste std::string member_name; 594254721Semaste 595254721Semaste ClangASTType member_clang_type = clang_type.GetFieldAtIndex (i, member_name, NULL, NULL, NULL); 596254721Semaste 597254721Semaste if (partial_member_name.empty() || 598254721Semaste member_name.find(partial_member_name) == 0) 599254721Semaste { 600254721Semaste if (member_name == partial_member_name) 601254721Semaste { 602254721Semaste PrivateAutoComplete (frame, 603254721Semaste partial_path, 604254721Semaste prefix_path + member_name, // Anything that has been resolved already will be in here 605254721Semaste member_clang_type.GetCanonicalType(), 606254721Semaste matches, 607254721Semaste word_complete); 608254721Semaste } 609254721Semaste else 610254721Semaste { 611254721Semaste matches.AppendString (prefix_path + member_name); 612254721Semaste } 613254721Semaste } 614254721Semaste } 615254721Semaste } 616254721Semaste} 617254721Semaste 618254721Semastestatic void 619254721SemastePrivateAutoComplete (StackFrame *frame, 620254721Semaste const std::string &partial_path, 621254721Semaste const std::string &prefix_path, // Anything that has been resolved already will be in here 622254721Semaste const ClangASTType& clang_type, 623254721Semaste StringList &matches, 624254721Semaste bool &word_complete) 625254721Semaste{ 626254721Semaste// printf ("\nPrivateAutoComplete()\n\tprefix_path = '%s'\n\tpartial_path = '%s'\n", prefix_path.c_str(), partial_path.c_str()); 627254721Semaste std::string remaining_partial_path; 628254721Semaste 629254721Semaste const lldb::TypeClass type_class = clang_type.GetTypeClass(); 630254721Semaste if (partial_path.empty()) 631254721Semaste { 632254721Semaste if (clang_type.IsValid()) 633254721Semaste { 634254721Semaste switch (type_class) 635254721Semaste { 636254721Semaste default: 637254721Semaste case eTypeClassArray: 638254721Semaste case eTypeClassBlockPointer: 639254721Semaste case eTypeClassBuiltin: 640254721Semaste case eTypeClassComplexFloat: 641254721Semaste case eTypeClassComplexInteger: 642254721Semaste case eTypeClassEnumeration: 643254721Semaste case eTypeClassFunction: 644254721Semaste case eTypeClassMemberPointer: 645254721Semaste case eTypeClassReference: 646254721Semaste case eTypeClassTypedef: 647254721Semaste case eTypeClassVector: 648254721Semaste { 649254721Semaste matches.AppendString (prefix_path); 650254721Semaste word_complete = matches.GetSize() == 1; 651254721Semaste } 652254721Semaste break; 653254721Semaste 654254721Semaste case eTypeClassClass: 655254721Semaste case eTypeClassStruct: 656254721Semaste case eTypeClassUnion: 657254721Semaste if (prefix_path.back() != '.') 658254721Semaste matches.AppendString (prefix_path + '.'); 659254721Semaste break; 660254721Semaste 661254721Semaste case eTypeClassObjCObject: 662254721Semaste case eTypeClassObjCInterface: 663254721Semaste break; 664254721Semaste case eTypeClassObjCObjectPointer: 665254721Semaste case eTypeClassPointer: 666254721Semaste { 667254721Semaste bool omit_empty_base_classes = true; 668254721Semaste if (clang_type.GetNumChildren (omit_empty_base_classes) > 0) 669254721Semaste matches.AppendString (prefix_path + "->"); 670254721Semaste else 671254721Semaste { 672254721Semaste matches.AppendString (prefix_path); 673254721Semaste word_complete = true; 674254721Semaste } 675254721Semaste } 676254721Semaste break; 677254721Semaste } 678254721Semaste } 679254721Semaste else 680254721Semaste { 681254721Semaste if (frame) 682254721Semaste { 683254721Semaste const bool get_file_globals = true; 684254721Semaste 685254721Semaste VariableList *variable_list = frame->GetVariableList(get_file_globals); 686254721Semaste 687263363Semaste if (variable_list) 688254721Semaste { 689263363Semaste const size_t num_variables = variable_list->GetSize(); 690263363Semaste for (size_t i=0; i<num_variables; ++i) 691263363Semaste { 692263363Semaste Variable *variable = variable_list->GetVariableAtIndex(i).get(); 693263363Semaste matches.AppendString (variable->GetName().AsCString()); 694263363Semaste } 695254721Semaste } 696254721Semaste } 697254721Semaste } 698254721Semaste } 699254721Semaste else 700254721Semaste { 701254721Semaste const char ch = partial_path[0]; 702254721Semaste switch (ch) 703254721Semaste { 704254721Semaste case '*': 705254721Semaste if (prefix_path.empty()) 706254721Semaste { 707254721Semaste PrivateAutoComplete (frame, 708254721Semaste partial_path.substr(1), 709254721Semaste std::string("*"), 710254721Semaste clang_type, 711254721Semaste matches, 712254721Semaste word_complete); 713254721Semaste } 714254721Semaste break; 715254721Semaste 716254721Semaste case '&': 717254721Semaste if (prefix_path.empty()) 718254721Semaste { 719254721Semaste PrivateAutoComplete (frame, 720254721Semaste partial_path.substr(1), 721254721Semaste std::string("&"), 722254721Semaste clang_type, 723254721Semaste matches, 724254721Semaste word_complete); 725254721Semaste } 726254721Semaste break; 727254721Semaste 728254721Semaste case '-': 729254721Semaste if (partial_path[1] == '>' && !prefix_path.empty()) 730254721Semaste { 731254721Semaste switch (type_class) 732254721Semaste { 733254721Semaste case lldb::eTypeClassPointer: 734254721Semaste { 735254721Semaste ClangASTType pointee_type(clang_type.GetPointeeType()); 736254721Semaste if (partial_path[2]) 737254721Semaste { 738254721Semaste // If there is more after the "->", then search deeper 739254721Semaste PrivateAutoComplete (frame, 740254721Semaste partial_path.substr(2), 741254721Semaste prefix_path + "->", 742254721Semaste pointee_type.GetCanonicalType(), 743254721Semaste matches, 744254721Semaste word_complete); 745254721Semaste } 746254721Semaste else 747254721Semaste { 748254721Semaste // Nothing after the "->", so list all members 749254721Semaste PrivateAutoCompleteMembers (frame, 750254721Semaste std::string(), 751254721Semaste std::string(), 752254721Semaste prefix_path + "->", 753254721Semaste pointee_type.GetCanonicalType(), 754254721Semaste matches, 755254721Semaste word_complete); 756254721Semaste } 757254721Semaste } 758254721Semaste default: 759254721Semaste break; 760254721Semaste } 761254721Semaste } 762254721Semaste break; 763254721Semaste 764254721Semaste case '.': 765254721Semaste if (clang_type.IsValid()) 766254721Semaste { 767254721Semaste switch (type_class) 768254721Semaste { 769254721Semaste case lldb::eTypeClassUnion: 770254721Semaste case lldb::eTypeClassStruct: 771254721Semaste case lldb::eTypeClassClass: 772254721Semaste if (partial_path[1]) 773254721Semaste { 774254721Semaste // If there is more after the ".", then search deeper 775254721Semaste PrivateAutoComplete (frame, 776254721Semaste partial_path.substr(1), 777254721Semaste prefix_path + ".", 778254721Semaste clang_type, 779254721Semaste matches, 780254721Semaste word_complete); 781254721Semaste 782254721Semaste } 783254721Semaste else 784254721Semaste { 785254721Semaste // Nothing after the ".", so list all members 786254721Semaste PrivateAutoCompleteMembers (frame, 787254721Semaste std::string(), 788254721Semaste partial_path, 789254721Semaste prefix_path + ".", 790254721Semaste clang_type, 791254721Semaste matches, 792254721Semaste word_complete); 793254721Semaste } 794254721Semaste default: 795254721Semaste break; 796254721Semaste } 797254721Semaste } 798254721Semaste break; 799254721Semaste default: 800254721Semaste if (isalpha(ch) || ch == '_' || ch == '$') 801254721Semaste { 802254721Semaste const size_t partial_path_len = partial_path.size(); 803254721Semaste size_t pos = 1; 804254721Semaste while (pos < partial_path_len) 805254721Semaste { 806254721Semaste const char curr_ch = partial_path[pos]; 807254721Semaste if (isalnum(curr_ch) || curr_ch == '_' || curr_ch == '$') 808254721Semaste { 809254721Semaste ++pos; 810254721Semaste continue; 811254721Semaste } 812254721Semaste break; 813254721Semaste } 814254721Semaste 815254721Semaste std::string token(partial_path, 0, pos); 816254721Semaste remaining_partial_path = partial_path.substr(pos); 817254721Semaste 818254721Semaste if (clang_type.IsValid()) 819254721Semaste { 820254721Semaste PrivateAutoCompleteMembers (frame, 821254721Semaste token, 822254721Semaste remaining_partial_path, 823254721Semaste prefix_path, 824254721Semaste clang_type, 825254721Semaste matches, 826254721Semaste word_complete); 827254721Semaste } 828254721Semaste else if (frame) 829254721Semaste { 830254721Semaste // We haven't found our variable yet 831254721Semaste const bool get_file_globals = true; 832254721Semaste 833254721Semaste VariableList *variable_list = frame->GetVariableList(get_file_globals); 834254721Semaste 835269024Semaste if (!variable_list) 836269024Semaste break; 837269024Semaste 838254721Semaste const size_t num_variables = variable_list->GetSize(); 839254721Semaste for (size_t i=0; i<num_variables; ++i) 840254721Semaste { 841254721Semaste Variable *variable = variable_list->GetVariableAtIndex(i).get(); 842269024Semaste 843269024Semaste if (!variable) 844269024Semaste continue; 845269024Semaste 846254721Semaste const char *variable_name = variable->GetName().AsCString(); 847254721Semaste if (strstr(variable_name, token.c_str()) == variable_name) 848254721Semaste { 849254721Semaste if (strcmp (variable_name, token.c_str()) == 0) 850254721Semaste { 851254721Semaste Type *variable_type = variable->GetType(); 852254721Semaste if (variable_type) 853254721Semaste { 854254721Semaste ClangASTType variable_clang_type (variable_type->GetClangForwardType()); 855254721Semaste PrivateAutoComplete (frame, 856254721Semaste remaining_partial_path, 857254721Semaste prefix_path + token, // Anything that has been resolved already will be in here 858254721Semaste variable_clang_type.GetCanonicalType(), 859254721Semaste matches, 860254721Semaste word_complete); 861254721Semaste } 862254721Semaste else 863254721Semaste { 864254721Semaste matches.AppendString (prefix_path + variable_name); 865254721Semaste } 866254721Semaste } 867254721Semaste else if (remaining_partial_path.empty()) 868254721Semaste { 869254721Semaste matches.AppendString (prefix_path + variable_name); 870254721Semaste } 871254721Semaste } 872254721Semaste } 873254721Semaste } 874254721Semaste } 875254721Semaste break; 876254721Semaste } 877254721Semaste } 878254721Semaste} 879254721Semaste 880254721Semaste 881254721Semaste 882254721Semastesize_t 883254721SemasteVariable::AutoComplete (const ExecutionContext &exe_ctx, 884254721Semaste const char *partial_path_cstr, 885254721Semaste StringList &matches, 886254721Semaste bool &word_complete) 887254721Semaste{ 888254721Semaste word_complete = false; 889254721Semaste std::string partial_path; 890254721Semaste std::string prefix_path; 891254721Semaste ClangASTType clang_type; 892254721Semaste if (partial_path_cstr && partial_path_cstr[0]) 893254721Semaste partial_path = partial_path_cstr; 894254721Semaste 895254721Semaste PrivateAutoComplete (exe_ctx.GetFramePtr(), 896254721Semaste partial_path, 897254721Semaste prefix_path, 898254721Semaste clang_type, 899254721Semaste matches, 900254721Semaste word_complete); 901254721Semaste 902254721Semaste return matches.GetSize(); 903254721Semaste} 904254721Semaste 905