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