1*4d93b8cdSEnrico Granata //===-- ValueObjectPrinter.cpp -------------------------------------*- C++ -*-===// 2*4d93b8cdSEnrico Granata // 3*4d93b8cdSEnrico Granata // The LLVM Compiler Infrastructure 4*4d93b8cdSEnrico Granata // 5*4d93b8cdSEnrico Granata // This file is distributed under the University of Illinois Open Source 6*4d93b8cdSEnrico Granata // License. See LICENSE.TXT for details. 7*4d93b8cdSEnrico Granata // 8*4d93b8cdSEnrico Granata //===----------------------------------------------------------------------===// 9*4d93b8cdSEnrico Granata 10*4d93b8cdSEnrico Granata #include "lldb/DataFormatters/ValueObjectPrinter.h" 11*4d93b8cdSEnrico Granata 12*4d93b8cdSEnrico Granata // C Includes 13*4d93b8cdSEnrico Granata // C++ Includes 14*4d93b8cdSEnrico Granata // Other libraries and framework includes 15*4d93b8cdSEnrico Granata // Project includes 16*4d93b8cdSEnrico Granata #include "lldb/Core/Debugger.h" 17*4d93b8cdSEnrico Granata #include "lldb/Interpreter/CommandInterpreter.h" 18*4d93b8cdSEnrico Granata #include "lldb/Target/Target.h" 19*4d93b8cdSEnrico Granata 20*4d93b8cdSEnrico Granata using namespace lldb; 21*4d93b8cdSEnrico Granata using namespace lldb_private; 22*4d93b8cdSEnrico Granata 23*4d93b8cdSEnrico Granata ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj, 24*4d93b8cdSEnrico Granata Stream* s, 25*4d93b8cdSEnrico Granata const DumpValueObjectOptions& options) : 26*4d93b8cdSEnrico Granata m_orig_valobj(valobj), 27*4d93b8cdSEnrico Granata m_valobj(nullptr), 28*4d93b8cdSEnrico Granata m_stream(s), 29*4d93b8cdSEnrico Granata options(options), 30*4d93b8cdSEnrico Granata m_ptr_depth(options.m_max_ptr_depth), 31*4d93b8cdSEnrico Granata m_curr_depth(0), 32*4d93b8cdSEnrico Granata m_should_print(eLazyBoolCalculate), 33*4d93b8cdSEnrico Granata m_is_nil(eLazyBoolCalculate), 34*4d93b8cdSEnrico Granata m_is_ptr(eLazyBoolCalculate), 35*4d93b8cdSEnrico Granata m_is_ref(eLazyBoolCalculate), 36*4d93b8cdSEnrico Granata m_is_aggregate(eLazyBoolCalculate), 37*4d93b8cdSEnrico Granata m_summary_formatter({nullptr,false}), 38*4d93b8cdSEnrico Granata m_value(), 39*4d93b8cdSEnrico Granata m_summary(), 40*4d93b8cdSEnrico Granata m_error() 41*4d93b8cdSEnrico Granata { 42*4d93b8cdSEnrico Granata assert (m_orig_valobj && "cannot print a NULL ValueObject"); 43*4d93b8cdSEnrico Granata assert (m_stream && "cannot print to a NULL Stream"); 44*4d93b8cdSEnrico Granata } 45*4d93b8cdSEnrico Granata 46*4d93b8cdSEnrico Granata ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj, 47*4d93b8cdSEnrico Granata Stream* s, 48*4d93b8cdSEnrico Granata const DumpValueObjectOptions& options, 49*4d93b8cdSEnrico Granata uint32_t ptr_depth, 50*4d93b8cdSEnrico Granata uint32_t curr_depth) : 51*4d93b8cdSEnrico Granata ValueObjectPrinter(valobj,s,options) 52*4d93b8cdSEnrico Granata { 53*4d93b8cdSEnrico Granata m_ptr_depth = ptr_depth; 54*4d93b8cdSEnrico Granata m_curr_depth = curr_depth; 55*4d93b8cdSEnrico Granata } 56*4d93b8cdSEnrico Granata 57*4d93b8cdSEnrico Granata bool 58*4d93b8cdSEnrico Granata ValueObjectPrinter::PrintValueObject () 59*4d93b8cdSEnrico Granata { 60*4d93b8cdSEnrico Granata if (!GetDynamicValueIfNeeded () || m_valobj == nullptr) 61*4d93b8cdSEnrico Granata return false; 62*4d93b8cdSEnrico Granata 63*4d93b8cdSEnrico Granata if (ShouldPrintValueObject()) 64*4d93b8cdSEnrico Granata { 65*4d93b8cdSEnrico Granata PrintLocationIfNeeded(); 66*4d93b8cdSEnrico Granata m_stream->Indent(); 67*4d93b8cdSEnrico Granata 68*4d93b8cdSEnrico Granata bool show_type = PrintTypeIfNeeded(); 69*4d93b8cdSEnrico Granata 70*4d93b8cdSEnrico Granata PrintNameIfNeeded(show_type); 71*4d93b8cdSEnrico Granata } 72*4d93b8cdSEnrico Granata 73*4d93b8cdSEnrico Granata bool value_printed = false; 74*4d93b8cdSEnrico Granata bool summary_printed = false; 75*4d93b8cdSEnrico Granata 76*4d93b8cdSEnrico Granata bool val_summary_ok = PrintValueAndSummaryIfNeeded (value_printed,summary_printed); 77*4d93b8cdSEnrico Granata 78*4d93b8cdSEnrico Granata if (val_summary_ok) 79*4d93b8cdSEnrico Granata PrintChildrenIfNeeded (value_printed, summary_printed); 80*4d93b8cdSEnrico Granata 81*4d93b8cdSEnrico Granata m_stream->EOL(); 82*4d93b8cdSEnrico Granata 83*4d93b8cdSEnrico Granata return true; 84*4d93b8cdSEnrico Granata } 85*4d93b8cdSEnrico Granata 86*4d93b8cdSEnrico Granata bool 87*4d93b8cdSEnrico Granata ValueObjectPrinter::GetDynamicValueIfNeeded () 88*4d93b8cdSEnrico Granata { 89*4d93b8cdSEnrico Granata bool update_success = m_orig_valobj->UpdateValueIfNeeded (true); 90*4d93b8cdSEnrico Granata if (!update_success) 91*4d93b8cdSEnrico Granata return false; 92*4d93b8cdSEnrico Granata if (options.m_use_dynamic != eNoDynamicValues) 93*4d93b8cdSEnrico Granata { 94*4d93b8cdSEnrico Granata ValueObject *dynamic_value = m_orig_valobj->GetDynamicValue(options.m_use_dynamic).get(); 95*4d93b8cdSEnrico Granata if (dynamic_value) 96*4d93b8cdSEnrico Granata m_valobj = dynamic_value; 97*4d93b8cdSEnrico Granata else 98*4d93b8cdSEnrico Granata m_valobj = m_orig_valobj; 99*4d93b8cdSEnrico Granata } 100*4d93b8cdSEnrico Granata else 101*4d93b8cdSEnrico Granata m_valobj = m_orig_valobj; 102*4d93b8cdSEnrico Granata m_clang_type = m_valobj->GetClangType(); 103*4d93b8cdSEnrico Granata m_type_flags = m_clang_type.GetTypeInfo (); 104*4d93b8cdSEnrico Granata return true; 105*4d93b8cdSEnrico Granata } 106*4d93b8cdSEnrico Granata 107*4d93b8cdSEnrico Granata const char* 108*4d93b8cdSEnrico Granata ValueObjectPrinter::GetDescriptionForDisplay () 109*4d93b8cdSEnrico Granata { 110*4d93b8cdSEnrico Granata const char* str = m_valobj->GetObjectDescription(); 111*4d93b8cdSEnrico Granata if (!str) 112*4d93b8cdSEnrico Granata str = m_valobj->GetSummaryAsCString(); 113*4d93b8cdSEnrico Granata if (!str) 114*4d93b8cdSEnrico Granata str = m_valobj->GetValueAsCString(); 115*4d93b8cdSEnrico Granata return str; 116*4d93b8cdSEnrico Granata } 117*4d93b8cdSEnrico Granata 118*4d93b8cdSEnrico Granata const char* 119*4d93b8cdSEnrico Granata ValueObjectPrinter::GetRootNameForDisplay (const char* if_fail) 120*4d93b8cdSEnrico Granata { 121*4d93b8cdSEnrico Granata const char *root_valobj_name = options.m_root_valobj_name.empty() ? 122*4d93b8cdSEnrico Granata m_valobj->GetName().AsCString() : 123*4d93b8cdSEnrico Granata options.m_root_valobj_name.c_str(); 124*4d93b8cdSEnrico Granata return root_valobj_name ? root_valobj_name : if_fail; 125*4d93b8cdSEnrico Granata } 126*4d93b8cdSEnrico Granata 127*4d93b8cdSEnrico Granata bool 128*4d93b8cdSEnrico Granata ValueObjectPrinter::ShouldPrintValueObject () 129*4d93b8cdSEnrico Granata { 130*4d93b8cdSEnrico Granata if (m_should_print == eLazyBoolCalculate) 131*4d93b8cdSEnrico Granata m_should_print = (options.m_flat_output == false || m_type_flags.Test (ClangASTType::eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo; 132*4d93b8cdSEnrico Granata return m_should_print == eLazyBoolYes; 133*4d93b8cdSEnrico Granata } 134*4d93b8cdSEnrico Granata 135*4d93b8cdSEnrico Granata bool 136*4d93b8cdSEnrico Granata ValueObjectPrinter::IsNil () 137*4d93b8cdSEnrico Granata { 138*4d93b8cdSEnrico Granata if (m_is_nil == eLazyBoolCalculate) 139*4d93b8cdSEnrico Granata m_is_nil = m_valobj->IsObjCNil() ? eLazyBoolYes : eLazyBoolNo; 140*4d93b8cdSEnrico Granata return m_is_nil == eLazyBoolYes; 141*4d93b8cdSEnrico Granata } 142*4d93b8cdSEnrico Granata 143*4d93b8cdSEnrico Granata bool 144*4d93b8cdSEnrico Granata ValueObjectPrinter::IsPtr () 145*4d93b8cdSEnrico Granata { 146*4d93b8cdSEnrico Granata if (m_is_ptr == eLazyBoolCalculate) 147*4d93b8cdSEnrico Granata m_is_ptr = m_type_flags.Test (ClangASTType::eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo; 148*4d93b8cdSEnrico Granata return m_is_ptr == eLazyBoolYes; 149*4d93b8cdSEnrico Granata } 150*4d93b8cdSEnrico Granata 151*4d93b8cdSEnrico Granata bool 152*4d93b8cdSEnrico Granata ValueObjectPrinter::IsRef () 153*4d93b8cdSEnrico Granata { 154*4d93b8cdSEnrico Granata if (m_is_ref == eLazyBoolCalculate) 155*4d93b8cdSEnrico Granata m_is_ref = m_type_flags.Test (ClangASTType::eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo; 156*4d93b8cdSEnrico Granata return m_is_ref == eLazyBoolYes; 157*4d93b8cdSEnrico Granata } 158*4d93b8cdSEnrico Granata 159*4d93b8cdSEnrico Granata bool 160*4d93b8cdSEnrico Granata ValueObjectPrinter::IsAggregate () 161*4d93b8cdSEnrico Granata { 162*4d93b8cdSEnrico Granata if (m_is_aggregate == eLazyBoolCalculate) 163*4d93b8cdSEnrico Granata m_is_aggregate = m_type_flags.Test (ClangASTType::eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo; 164*4d93b8cdSEnrico Granata return m_is_aggregate == eLazyBoolYes; 165*4d93b8cdSEnrico Granata } 166*4d93b8cdSEnrico Granata 167*4d93b8cdSEnrico Granata bool 168*4d93b8cdSEnrico Granata ValueObjectPrinter::PrintLocationIfNeeded () 169*4d93b8cdSEnrico Granata { 170*4d93b8cdSEnrico Granata if (options.m_show_location) 171*4d93b8cdSEnrico Granata { 172*4d93b8cdSEnrico Granata m_stream->Printf("%s: ", m_valobj->GetLocationAsCString()); 173*4d93b8cdSEnrico Granata return true; 174*4d93b8cdSEnrico Granata } 175*4d93b8cdSEnrico Granata return false; 176*4d93b8cdSEnrico Granata } 177*4d93b8cdSEnrico Granata 178*4d93b8cdSEnrico Granata bool 179*4d93b8cdSEnrico Granata ValueObjectPrinter::PrintTypeIfNeeded () 180*4d93b8cdSEnrico Granata { 181*4d93b8cdSEnrico Granata bool show_type = true; 182*4d93b8cdSEnrico Granata // if we are at the root-level and been asked to hide the root's type, then hide it 183*4d93b8cdSEnrico Granata if (m_curr_depth == 0 && options.m_hide_root_type) 184*4d93b8cdSEnrico Granata show_type = false; 185*4d93b8cdSEnrico Granata else 186*4d93b8cdSEnrico Granata // otherwise decide according to the usual rules (asked to show types - always at the root level) 187*4d93b8cdSEnrico Granata show_type = options.m_show_types || (m_curr_depth == 0 && !options.m_flat_output); 188*4d93b8cdSEnrico Granata 189*4d93b8cdSEnrico Granata if (show_type) 190*4d93b8cdSEnrico Granata { 191*4d93b8cdSEnrico Granata // Some ValueObjects don't have types (like registers sets). Only print 192*4d93b8cdSEnrico Granata // the type if there is one to print 193*4d93b8cdSEnrico Granata ConstString qualified_type_name(m_valobj->GetQualifiedTypeName()); 194*4d93b8cdSEnrico Granata if (qualified_type_name) 195*4d93b8cdSEnrico Granata m_stream->Printf("(%s) ", qualified_type_name.GetCString()); 196*4d93b8cdSEnrico Granata else 197*4d93b8cdSEnrico Granata show_type = false; 198*4d93b8cdSEnrico Granata } 199*4d93b8cdSEnrico Granata return show_type; 200*4d93b8cdSEnrico Granata } 201*4d93b8cdSEnrico Granata 202*4d93b8cdSEnrico Granata bool 203*4d93b8cdSEnrico Granata ValueObjectPrinter::PrintNameIfNeeded (bool show_type) 204*4d93b8cdSEnrico Granata { 205*4d93b8cdSEnrico Granata if (options.m_flat_output) 206*4d93b8cdSEnrico Granata { 207*4d93b8cdSEnrico Granata // If we are showing types, also qualify the C++ base classes 208*4d93b8cdSEnrico Granata const bool qualify_cxx_base_classes = show_type; 209*4d93b8cdSEnrico Granata if (!options.m_hide_name) 210*4d93b8cdSEnrico Granata { 211*4d93b8cdSEnrico Granata m_valobj->GetExpressionPath(*m_stream, qualify_cxx_base_classes); 212*4d93b8cdSEnrico Granata m_stream->PutCString(" ="); 213*4d93b8cdSEnrico Granata return true; 214*4d93b8cdSEnrico Granata } 215*4d93b8cdSEnrico Granata } 216*4d93b8cdSEnrico Granata else if (!options.m_hide_name) 217*4d93b8cdSEnrico Granata { 218*4d93b8cdSEnrico Granata const char *name_cstr = GetRootNameForDisplay(""); 219*4d93b8cdSEnrico Granata m_stream->Printf ("%s =", name_cstr); 220*4d93b8cdSEnrico Granata return true; 221*4d93b8cdSEnrico Granata } 222*4d93b8cdSEnrico Granata return false; 223*4d93b8cdSEnrico Granata } 224*4d93b8cdSEnrico Granata 225*4d93b8cdSEnrico Granata bool 226*4d93b8cdSEnrico Granata ValueObjectPrinter::CheckScopeIfNeeded () 227*4d93b8cdSEnrico Granata { 228*4d93b8cdSEnrico Granata if (options.m_scope_already_checked) 229*4d93b8cdSEnrico Granata return true; 230*4d93b8cdSEnrico Granata return m_valobj->IsInScope(); 231*4d93b8cdSEnrico Granata } 232*4d93b8cdSEnrico Granata 233*4d93b8cdSEnrico Granata TypeSummaryImpl* 234*4d93b8cdSEnrico Granata ValueObjectPrinter::GetSummaryFormatter () 235*4d93b8cdSEnrico Granata { 236*4d93b8cdSEnrico Granata if (m_summary_formatter.second == false) 237*4d93b8cdSEnrico Granata { 238*4d93b8cdSEnrico Granata TypeSummaryImpl* entry = options.m_summary_sp ? options.m_summary_sp.get() : m_valobj->GetSummaryFormat().get(); 239*4d93b8cdSEnrico Granata 240*4d93b8cdSEnrico Granata if (options.m_omit_summary_depth > 0) 241*4d93b8cdSEnrico Granata entry = NULL; 242*4d93b8cdSEnrico Granata m_summary_formatter.first = entry; 243*4d93b8cdSEnrico Granata m_summary_formatter.second = true; 244*4d93b8cdSEnrico Granata } 245*4d93b8cdSEnrico Granata return m_summary_formatter.first; 246*4d93b8cdSEnrico Granata } 247*4d93b8cdSEnrico Granata 248*4d93b8cdSEnrico Granata void 249*4d93b8cdSEnrico Granata ValueObjectPrinter::GetValueSummaryError (std::string& value, 250*4d93b8cdSEnrico Granata std::string& summary, 251*4d93b8cdSEnrico Granata std::string& error) 252*4d93b8cdSEnrico Granata { 253*4d93b8cdSEnrico Granata if (options.m_format != eFormatDefault && options.m_format != m_valobj->GetFormat()) 254*4d93b8cdSEnrico Granata { 255*4d93b8cdSEnrico Granata m_valobj->GetValueAsCString(options.m_format, 256*4d93b8cdSEnrico Granata value); 257*4d93b8cdSEnrico Granata } 258*4d93b8cdSEnrico Granata else 259*4d93b8cdSEnrico Granata { 260*4d93b8cdSEnrico Granata const char* val_cstr = m_valobj->GetValueAsCString(); 261*4d93b8cdSEnrico Granata if (val_cstr) 262*4d93b8cdSEnrico Granata value.assign(val_cstr); 263*4d93b8cdSEnrico Granata } 264*4d93b8cdSEnrico Granata const char* err_cstr = m_valobj->GetError().AsCString(); 265*4d93b8cdSEnrico Granata if (err_cstr) 266*4d93b8cdSEnrico Granata error.assign(err_cstr); 267*4d93b8cdSEnrico Granata 268*4d93b8cdSEnrico Granata if (ShouldPrintValueObject()) 269*4d93b8cdSEnrico Granata { 270*4d93b8cdSEnrico Granata if (IsNil()) 271*4d93b8cdSEnrico Granata summary.assign("nil"); 272*4d93b8cdSEnrico Granata else if (options.m_omit_summary_depth == 0) 273*4d93b8cdSEnrico Granata { 274*4d93b8cdSEnrico Granata TypeSummaryImpl* entry = GetSummaryFormatter(); 275*4d93b8cdSEnrico Granata if (entry) 276*4d93b8cdSEnrico Granata m_valobj->GetSummaryAsCString(entry, summary); 277*4d93b8cdSEnrico Granata else 278*4d93b8cdSEnrico Granata { 279*4d93b8cdSEnrico Granata const char* sum_cstr = m_valobj->GetSummaryAsCString(); 280*4d93b8cdSEnrico Granata if (sum_cstr) 281*4d93b8cdSEnrico Granata summary.assign(sum_cstr); 282*4d93b8cdSEnrico Granata } 283*4d93b8cdSEnrico Granata } 284*4d93b8cdSEnrico Granata } 285*4d93b8cdSEnrico Granata } 286*4d93b8cdSEnrico Granata 287*4d93b8cdSEnrico Granata bool 288*4d93b8cdSEnrico Granata ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed, 289*4d93b8cdSEnrico Granata bool& summary_printed) 290*4d93b8cdSEnrico Granata { 291*4d93b8cdSEnrico Granata bool error_printed = false; 292*4d93b8cdSEnrico Granata if (ShouldPrintValueObject()) 293*4d93b8cdSEnrico Granata { 294*4d93b8cdSEnrico Granata if (!CheckScopeIfNeeded()) 295*4d93b8cdSEnrico Granata m_error.assign("out of scope"); 296*4d93b8cdSEnrico Granata if (m_error.empty()) 297*4d93b8cdSEnrico Granata { 298*4d93b8cdSEnrico Granata GetValueSummaryError(m_value, m_summary, m_error); 299*4d93b8cdSEnrico Granata } 300*4d93b8cdSEnrico Granata if (m_error.size()) 301*4d93b8cdSEnrico Granata { 302*4d93b8cdSEnrico Granata error_printed = true; 303*4d93b8cdSEnrico Granata m_stream->Printf (" <%s>\n", m_error.c_str()); 304*4d93b8cdSEnrico Granata } 305*4d93b8cdSEnrico Granata else 306*4d93b8cdSEnrico Granata { 307*4d93b8cdSEnrico Granata // Make sure we have a value and make sure the summary didn't 308*4d93b8cdSEnrico Granata // specify that the value should not be printed - and do not print 309*4d93b8cdSEnrico Granata // the value if this thing is nil 310*4d93b8cdSEnrico Granata // (but show the value if the user passes a format explicitly) 311*4d93b8cdSEnrico Granata TypeSummaryImpl* entry = GetSummaryFormatter(); 312*4d93b8cdSEnrico Granata if (!IsNil() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue() || options.m_format != eFormatDefault) || m_summary.empty()) && !options.m_hide_value) 313*4d93b8cdSEnrico Granata { 314*4d93b8cdSEnrico Granata m_stream->Printf(" %s", m_value.c_str()); 315*4d93b8cdSEnrico Granata value_printed = true; 316*4d93b8cdSEnrico Granata } 317*4d93b8cdSEnrico Granata 318*4d93b8cdSEnrico Granata if (m_summary.size()) 319*4d93b8cdSEnrico Granata { 320*4d93b8cdSEnrico Granata m_stream->Printf(" %s", m_summary.c_str()); 321*4d93b8cdSEnrico Granata summary_printed = true; 322*4d93b8cdSEnrico Granata } 323*4d93b8cdSEnrico Granata } 324*4d93b8cdSEnrico Granata } 325*4d93b8cdSEnrico Granata return !error_printed; 326*4d93b8cdSEnrico Granata } 327*4d93b8cdSEnrico Granata 328*4d93b8cdSEnrico Granata bool 329*4d93b8cdSEnrico Granata ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed, 330*4d93b8cdSEnrico Granata bool summary_printed) 331*4d93b8cdSEnrico Granata { 332*4d93b8cdSEnrico Granata if (ShouldPrintValueObject()) 333*4d93b8cdSEnrico Granata { 334*4d93b8cdSEnrico Granata // let's avoid the overly verbose no description error for a nil thing 335*4d93b8cdSEnrico Granata if (options.m_use_objc && !IsNil()) 336*4d93b8cdSEnrico Granata { 337*4d93b8cdSEnrico Granata if (!options.m_hide_value || !options.m_hide_name) 338*4d93b8cdSEnrico Granata m_stream->Printf(" "); 339*4d93b8cdSEnrico Granata const char *object_desc = nullptr; 340*4d93b8cdSEnrico Granata if (value_printed || summary_printed) 341*4d93b8cdSEnrico Granata object_desc = m_valobj->GetObjectDescription(); 342*4d93b8cdSEnrico Granata else 343*4d93b8cdSEnrico Granata object_desc = GetDescriptionForDisplay(); 344*4d93b8cdSEnrico Granata if (object_desc && *object_desc) 345*4d93b8cdSEnrico Granata { 346*4d93b8cdSEnrico Granata m_stream->Printf("%s\n", object_desc); 347*4d93b8cdSEnrico Granata return true; 348*4d93b8cdSEnrico Granata } 349*4d93b8cdSEnrico Granata else if (value_printed == false && summary_printed == false) 350*4d93b8cdSEnrico Granata return true; 351*4d93b8cdSEnrico Granata else 352*4d93b8cdSEnrico Granata return false; 353*4d93b8cdSEnrico Granata } 354*4d93b8cdSEnrico Granata } 355*4d93b8cdSEnrico Granata return true; 356*4d93b8cdSEnrico Granata } 357*4d93b8cdSEnrico Granata 358*4d93b8cdSEnrico Granata bool 359*4d93b8cdSEnrico Granata ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description, 360*4d93b8cdSEnrico Granata uint32_t& curr_ptr_depth) 361*4d93b8cdSEnrico Granata { 362*4d93b8cdSEnrico Granata const bool is_ref = IsRef (); 363*4d93b8cdSEnrico Granata const bool is_ptr = IsPtr (); 364*4d93b8cdSEnrico Granata 365*4d93b8cdSEnrico Granata if (is_failed_description || m_curr_depth < options.m_max_depth) 366*4d93b8cdSEnrico Granata { 367*4d93b8cdSEnrico Granata // We will show children for all concrete types. We won't show 368*4d93b8cdSEnrico Granata // pointer contents unless a pointer depth has been specified. 369*4d93b8cdSEnrico Granata // We won't reference contents unless the reference is the 370*4d93b8cdSEnrico Granata // root object (depth of zero). 371*4d93b8cdSEnrico Granata 372*4d93b8cdSEnrico Granata // Use a new temporary pointer depth in case we override the 373*4d93b8cdSEnrico Granata // current pointer depth below... 374*4d93b8cdSEnrico Granata uint32_t curr_ptr_depth = m_ptr_depth; 375*4d93b8cdSEnrico Granata 376*4d93b8cdSEnrico Granata if (is_ptr || is_ref) 377*4d93b8cdSEnrico Granata { 378*4d93b8cdSEnrico Granata // We have a pointer or reference whose value is an address. 379*4d93b8cdSEnrico Granata // Make sure that address is not NULL 380*4d93b8cdSEnrico Granata AddressType ptr_address_type; 381*4d93b8cdSEnrico Granata if (m_valobj->GetPointerValue (&ptr_address_type) == 0) 382*4d93b8cdSEnrico Granata return false; 383*4d93b8cdSEnrico Granata 384*4d93b8cdSEnrico Granata else if (is_ref && m_curr_depth == 0) 385*4d93b8cdSEnrico Granata { 386*4d93b8cdSEnrico Granata // If this is the root object (depth is zero) that we are showing 387*4d93b8cdSEnrico Granata // and it is a reference, and no pointer depth has been supplied 388*4d93b8cdSEnrico Granata // print out what it references. Don't do this at deeper depths 389*4d93b8cdSEnrico Granata // otherwise we can end up with infinite recursion... 390*4d93b8cdSEnrico Granata curr_ptr_depth = 1; 391*4d93b8cdSEnrico Granata } 392*4d93b8cdSEnrico Granata 393*4d93b8cdSEnrico Granata if (curr_ptr_depth == 0) 394*4d93b8cdSEnrico Granata return false; 395*4d93b8cdSEnrico Granata } 396*4d93b8cdSEnrico Granata 397*4d93b8cdSEnrico Granata TypeSummaryImpl* entry = GetSummaryFormatter(); 398*4d93b8cdSEnrico Granata 399*4d93b8cdSEnrico Granata return (!entry || entry->DoesPrintChildren() || m_summary.empty()); 400*4d93b8cdSEnrico Granata } 401*4d93b8cdSEnrico Granata return false; 402*4d93b8cdSEnrico Granata } 403*4d93b8cdSEnrico Granata 404*4d93b8cdSEnrico Granata ValueObject* 405*4d93b8cdSEnrico Granata ValueObjectPrinter::GetValueObjectForChildrenGeneration () 406*4d93b8cdSEnrico Granata { 407*4d93b8cdSEnrico Granata ValueObjectSP synth_valobj_sp = m_valobj->GetSyntheticValue (options.m_use_synthetic); 408*4d93b8cdSEnrico Granata return (synth_valobj_sp ? synth_valobj_sp.get() : m_valobj); 409*4d93b8cdSEnrico Granata } 410*4d93b8cdSEnrico Granata 411*4d93b8cdSEnrico Granata void 412*4d93b8cdSEnrico Granata ValueObjectPrinter::PrintChildrenPreamble () 413*4d93b8cdSEnrico Granata { 414*4d93b8cdSEnrico Granata if (options.m_flat_output) 415*4d93b8cdSEnrico Granata { 416*4d93b8cdSEnrico Granata if (ShouldPrintValueObject()) 417*4d93b8cdSEnrico Granata m_stream->EOL(); 418*4d93b8cdSEnrico Granata } 419*4d93b8cdSEnrico Granata else 420*4d93b8cdSEnrico Granata { 421*4d93b8cdSEnrico Granata if (ShouldPrintValueObject()) 422*4d93b8cdSEnrico Granata m_stream->PutCString(IsRef () ? ": {\n" : " {\n"); 423*4d93b8cdSEnrico Granata m_stream->IndentMore(); 424*4d93b8cdSEnrico Granata } 425*4d93b8cdSEnrico Granata } 426*4d93b8cdSEnrico Granata 427*4d93b8cdSEnrico Granata void 428*4d93b8cdSEnrico Granata ValueObjectPrinter::PrintChild (ValueObjectSP child_sp, 429*4d93b8cdSEnrico Granata uint32_t curr_ptr_depth) 430*4d93b8cdSEnrico Granata { 431*4d93b8cdSEnrico Granata DumpValueObjectOptions child_options(options); 432*4d93b8cdSEnrico Granata child_options.SetFormat(options.m_format).SetSummary().SetRootValueObjectName(); 433*4d93b8cdSEnrico Granata child_options.SetScopeChecked(true).SetHideName(options.m_hide_name).SetHideValue(options.m_hide_value) 434*4d93b8cdSEnrico Granata .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0); 435*4d93b8cdSEnrico Granata if (child_sp.get()) 436*4d93b8cdSEnrico Granata { 437*4d93b8cdSEnrico Granata ValueObjectPrinter child_printer(child_sp.get(), 438*4d93b8cdSEnrico Granata m_stream, 439*4d93b8cdSEnrico Granata child_options, 440*4d93b8cdSEnrico Granata (IsPtr() || IsRef()) ? curr_ptr_depth - 1 : curr_ptr_depth, 441*4d93b8cdSEnrico Granata m_curr_depth + 1); 442*4d93b8cdSEnrico Granata child_printer.PrintValueObject(); 443*4d93b8cdSEnrico Granata } 444*4d93b8cdSEnrico Granata 445*4d93b8cdSEnrico Granata } 446*4d93b8cdSEnrico Granata 447*4d93b8cdSEnrico Granata uint32_t 448*4d93b8cdSEnrico Granata ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot) 449*4d93b8cdSEnrico Granata { 450*4d93b8cdSEnrico Granata ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 451*4d93b8cdSEnrico Granata 452*4d93b8cdSEnrico Granata size_t num_children = synth_m_valobj->GetNumChildren(); 453*4d93b8cdSEnrico Granata print_dotdotdot = false; 454*4d93b8cdSEnrico Granata if (num_children) 455*4d93b8cdSEnrico Granata { 456*4d93b8cdSEnrico Granata const size_t max_num_children = m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); 457*4d93b8cdSEnrico Granata 458*4d93b8cdSEnrico Granata if (num_children > max_num_children && !options.m_ignore_cap) 459*4d93b8cdSEnrico Granata { 460*4d93b8cdSEnrico Granata print_dotdotdot = true; 461*4d93b8cdSEnrico Granata return max_num_children; 462*4d93b8cdSEnrico Granata } 463*4d93b8cdSEnrico Granata } 464*4d93b8cdSEnrico Granata return num_children; 465*4d93b8cdSEnrico Granata } 466*4d93b8cdSEnrico Granata 467*4d93b8cdSEnrico Granata void 468*4d93b8cdSEnrico Granata ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot) 469*4d93b8cdSEnrico Granata { 470*4d93b8cdSEnrico Granata if (!options.m_flat_output) 471*4d93b8cdSEnrico Granata { 472*4d93b8cdSEnrico Granata if (print_dotdotdot) 473*4d93b8cdSEnrico Granata { 474*4d93b8cdSEnrico Granata m_valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().ChildrenTruncated(); 475*4d93b8cdSEnrico Granata m_stream->Indent("...\n"); 476*4d93b8cdSEnrico Granata } 477*4d93b8cdSEnrico Granata m_stream->IndentLess(); 478*4d93b8cdSEnrico Granata m_stream->Indent("}\n"); 479*4d93b8cdSEnrico Granata } 480*4d93b8cdSEnrico Granata } 481*4d93b8cdSEnrico Granata 482*4d93b8cdSEnrico Granata void 483*4d93b8cdSEnrico Granata ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth) 484*4d93b8cdSEnrico Granata { 485*4d93b8cdSEnrico Granata ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); 486*4d93b8cdSEnrico Granata 487*4d93b8cdSEnrico Granata bool print_dotdotdot = false; 488*4d93b8cdSEnrico Granata size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); 489*4d93b8cdSEnrico Granata if (num_children) 490*4d93b8cdSEnrico Granata { 491*4d93b8cdSEnrico Granata PrintChildrenPreamble (); 492*4d93b8cdSEnrico Granata 493*4d93b8cdSEnrico Granata for (size_t idx=0; idx<num_children; ++idx) 494*4d93b8cdSEnrico Granata { 495*4d93b8cdSEnrico Granata ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true)); 496*4d93b8cdSEnrico Granata PrintChild (child_sp, curr_ptr_depth); 497*4d93b8cdSEnrico Granata } 498*4d93b8cdSEnrico Granata 499*4d93b8cdSEnrico Granata PrintChildrenPostamble (print_dotdotdot); 500*4d93b8cdSEnrico Granata } 501*4d93b8cdSEnrico Granata else if (IsAggregate()) 502*4d93b8cdSEnrico Granata { 503*4d93b8cdSEnrico Granata // Aggregate, no children... 504*4d93b8cdSEnrico Granata if (ShouldPrintValueObject()) 505*4d93b8cdSEnrico Granata m_stream->PutCString(" {}\n"); 506*4d93b8cdSEnrico Granata } 507*4d93b8cdSEnrico Granata else 508*4d93b8cdSEnrico Granata { 509*4d93b8cdSEnrico Granata if (ShouldPrintValueObject()) 510*4d93b8cdSEnrico Granata m_stream->EOL(); 511*4d93b8cdSEnrico Granata } 512*4d93b8cdSEnrico Granata } 513*4d93b8cdSEnrico Granata 514*4d93b8cdSEnrico Granata void 515*4d93b8cdSEnrico Granata ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed, 516*4d93b8cdSEnrico Granata bool summary_printed) 517*4d93b8cdSEnrico Granata { 518*4d93b8cdSEnrico Granata // this flag controls whether we tried to display a description for this object and failed 519*4d93b8cdSEnrico Granata // if that happens, we want to display the children, if any 520*4d93b8cdSEnrico Granata bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed); 521*4d93b8cdSEnrico Granata 522*4d93b8cdSEnrico Granata uint32_t curr_ptr_depth = m_ptr_depth; 523*4d93b8cdSEnrico Granata bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth); 524*4d93b8cdSEnrico Granata 525*4d93b8cdSEnrico Granata if (print_children) 526*4d93b8cdSEnrico Granata { 527*4d93b8cdSEnrico Granata PrintChildren (curr_ptr_depth); 528*4d93b8cdSEnrico Granata } 529*4d93b8cdSEnrico Granata else if (m_curr_depth >= options.m_max_depth && IsAggregate() && ShouldPrintValueObject()) 530*4d93b8cdSEnrico Granata { 531*4d93b8cdSEnrico Granata m_stream->PutCString("{...}\n"); 532*4d93b8cdSEnrico Granata } 533*4d93b8cdSEnrico Granata } 534