14d93b8cdSEnrico Granata //===-- ValueObjectPrinter.cpp -------------------------------------*- C++ -*-===//
24d93b8cdSEnrico Granata //
34d93b8cdSEnrico Granata //                     The LLVM Compiler Infrastructure
44d93b8cdSEnrico Granata //
54d93b8cdSEnrico Granata // This file is distributed under the University of Illinois Open Source
64d93b8cdSEnrico Granata // License. See LICENSE.TXT for details.
74d93b8cdSEnrico Granata //
84d93b8cdSEnrico Granata //===----------------------------------------------------------------------===//
94d93b8cdSEnrico Granata 
104d93b8cdSEnrico Granata #include "lldb/DataFormatters/ValueObjectPrinter.h"
114d93b8cdSEnrico Granata 
124d93b8cdSEnrico Granata // C Includes
134d93b8cdSEnrico Granata // C++ Includes
144d93b8cdSEnrico Granata // Other libraries and framework includes
154d93b8cdSEnrico Granata // Project includes
164d93b8cdSEnrico Granata #include "lldb/Core/Debugger.h"
17a29cb0baSEnrico Granata #include "lldb/DataFormatters/DataVisualization.h"
184d93b8cdSEnrico Granata #include "lldb/Interpreter/CommandInterpreter.h"
194d93b8cdSEnrico Granata #include "lldb/Target/Target.h"
204d93b8cdSEnrico Granata 
214d93b8cdSEnrico Granata using namespace lldb;
224d93b8cdSEnrico Granata using namespace lldb_private;
234d93b8cdSEnrico Granata 
24d5957336SEnrico Granata DumpValueObjectOptions::DumpValueObjectOptions (ValueObject& valobj) :
25d5957336SEnrico Granata DumpValueObjectOptions()
26d5957336SEnrico Granata {
27d5957336SEnrico Granata     m_use_dynamic = valobj.GetDynamicValueType();
28d5957336SEnrico Granata     m_use_synthetic = valobj.IsSynthetic();
29*73e8c4d0SEnrico Granata     m_varformat_language = valobj.GetPreferredDisplayLanguage();
30d5957336SEnrico Granata }
31d5957336SEnrico Granata 
32d5957336SEnrico Granata ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
33d5957336SEnrico Granata                                         Stream* s)
34d5957336SEnrico Granata {
35d5957336SEnrico Granata     if (valobj)
36d5957336SEnrico Granata     {
37d5957336SEnrico Granata         DumpValueObjectOptions options(*valobj);
38d5957336SEnrico Granata         Init (valobj,s,options,options.m_max_ptr_depth,0);
39d5957336SEnrico Granata     }
40d5957336SEnrico Granata     else
41d5957336SEnrico Granata     {
42d5957336SEnrico Granata         DumpValueObjectOptions options;
43d5957336SEnrico Granata         Init (valobj,s,options,options.m_max_ptr_depth,0);
44d5957336SEnrico Granata     }
45d5957336SEnrico Granata }
46d5957336SEnrico Granata 
474d93b8cdSEnrico Granata ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
484d93b8cdSEnrico Granata                                         Stream* s,
49938d1d67SEnrico Granata                                         const DumpValueObjectOptions& options)
504d93b8cdSEnrico Granata {
51938d1d67SEnrico Granata     Init(valobj,s,options,options.m_max_ptr_depth,0);
524d93b8cdSEnrico Granata }
534d93b8cdSEnrico Granata 
544d93b8cdSEnrico Granata ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
554d93b8cdSEnrico Granata                                         Stream* s,
564d93b8cdSEnrico Granata                                         const DumpValueObjectOptions& options,
57c1b7c09aSEnrico Granata                                         const DumpValueObjectOptions::PointerDepth& ptr_depth,
58938d1d67SEnrico Granata                                         uint32_t curr_depth)
59938d1d67SEnrico Granata {
60938d1d67SEnrico Granata     Init(valobj,s,options,ptr_depth,curr_depth);
61938d1d67SEnrico Granata }
62938d1d67SEnrico Granata 
63938d1d67SEnrico Granata void
64938d1d67SEnrico Granata ValueObjectPrinter::Init (ValueObject* valobj,
65938d1d67SEnrico Granata                           Stream* s,
66938d1d67SEnrico Granata                           const DumpValueObjectOptions& options,
67c1b7c09aSEnrico Granata                           const DumpValueObjectOptions::PointerDepth& ptr_depth,
68938d1d67SEnrico Granata                           uint32_t curr_depth)
69938d1d67SEnrico Granata {
70938d1d67SEnrico Granata     m_orig_valobj = valobj;
71938d1d67SEnrico Granata     m_valobj = nullptr;
72938d1d67SEnrico Granata     m_stream = s;
73938d1d67SEnrico Granata     this->options = options;
74938d1d67SEnrico Granata     m_ptr_depth = ptr_depth;
75938d1d67SEnrico Granata     m_curr_depth = curr_depth;
76938d1d67SEnrico Granata     assert (m_orig_valobj && "cannot print a NULL ValueObject");
77938d1d67SEnrico Granata     assert (m_stream && "cannot print to a NULL Stream");
78938d1d67SEnrico Granata     m_should_print = eLazyBoolCalculate;
79938d1d67SEnrico Granata     m_is_nil = eLazyBoolCalculate;
80938d1d67SEnrico Granata     m_is_ptr = eLazyBoolCalculate;
81938d1d67SEnrico Granata     m_is_ref = eLazyBoolCalculate;
82938d1d67SEnrico Granata     m_is_aggregate = eLazyBoolCalculate;
83938d1d67SEnrico Granata     m_summary_formatter = {nullptr,false};
84938d1d67SEnrico Granata     m_value.assign("");
85938d1d67SEnrico Granata     m_summary.assign("");
86938d1d67SEnrico Granata     m_error.assign("");
87938d1d67SEnrico Granata }
884d93b8cdSEnrico Granata 
894d93b8cdSEnrico Granata bool
904d93b8cdSEnrico Granata ValueObjectPrinter::PrintValueObject ()
914d93b8cdSEnrico Granata {
92d07cfd3aSEnrico Granata     if (!GetMostSpecializedValue () || m_valobj == nullptr)
934d93b8cdSEnrico Granata         return false;
944d93b8cdSEnrico Granata 
954d93b8cdSEnrico Granata     if (ShouldPrintValueObject())
964d93b8cdSEnrico Granata     {
970f883ffbSEnrico Granata         PrintValidationMarkerIfNeeded();
980f883ffbSEnrico Granata 
994d93b8cdSEnrico Granata         PrintLocationIfNeeded();
1004d93b8cdSEnrico Granata         m_stream->Indent();
1014d93b8cdSEnrico Granata 
1024d93b8cdSEnrico Granata         bool show_type = PrintTypeIfNeeded();
1034d93b8cdSEnrico Granata 
1044d93b8cdSEnrico Granata         PrintNameIfNeeded(show_type);
1054d93b8cdSEnrico Granata     }
1064d93b8cdSEnrico Granata 
1074d93b8cdSEnrico Granata     bool value_printed = false;
1084d93b8cdSEnrico Granata     bool summary_printed = false;
1094d93b8cdSEnrico Granata 
1104d93b8cdSEnrico Granata     bool val_summary_ok = PrintValueAndSummaryIfNeeded (value_printed,summary_printed);
1114d93b8cdSEnrico Granata 
1124d93b8cdSEnrico Granata     if (val_summary_ok)
1134d93b8cdSEnrico Granata         PrintChildrenIfNeeded (value_printed, summary_printed);
11439938938SEnrico Granata     else
1154d93b8cdSEnrico Granata         m_stream->EOL();
1164d93b8cdSEnrico Granata 
1170f883ffbSEnrico Granata     PrintValidationErrorIfNeeded();
1180f883ffbSEnrico Granata 
1194d93b8cdSEnrico Granata     return true;
1204d93b8cdSEnrico Granata }
1214d93b8cdSEnrico Granata 
1224d93b8cdSEnrico Granata bool
123d07cfd3aSEnrico Granata ValueObjectPrinter::GetMostSpecializedValue ()
1244d93b8cdSEnrico Granata {
125a29cb0baSEnrico Granata     if (m_valobj)
126a29cb0baSEnrico Granata         return true;
1274d93b8cdSEnrico Granata     bool update_success = m_orig_valobj->UpdateValueIfNeeded (true);
1284d93b8cdSEnrico Granata     if (!update_success)
129106260c5SEnrico Granata     {
130106260c5SEnrico Granata         m_valobj = m_orig_valobj;
131106260c5SEnrico Granata     }
132106260c5SEnrico Granata     else
133106260c5SEnrico Granata     {
134106260c5SEnrico Granata         if (m_orig_valobj->IsDynamic())
135106260c5SEnrico Granata         {
136106260c5SEnrico Granata             if (options.m_use_dynamic == eNoDynamicValues)
137106260c5SEnrico Granata             {
138106260c5SEnrico Granata                 ValueObject *static_value = m_orig_valobj->GetStaticValue().get();
139106260c5SEnrico Granata                 if (static_value)
140106260c5SEnrico Granata                     m_valobj = static_value;
141106260c5SEnrico Granata                 else
142106260c5SEnrico Granata                     m_valobj = m_orig_valobj;
143106260c5SEnrico Granata             }
144106260c5SEnrico Granata             else
145106260c5SEnrico Granata                 m_valobj = m_orig_valobj;
146106260c5SEnrico Granata         }
147106260c5SEnrico Granata         else
148106260c5SEnrico Granata         {
1494d93b8cdSEnrico Granata             if (options.m_use_dynamic != eNoDynamicValues)
1504d93b8cdSEnrico Granata             {
1514d93b8cdSEnrico Granata                 ValueObject *dynamic_value = m_orig_valobj->GetDynamicValue(options.m_use_dynamic).get();
1524d93b8cdSEnrico Granata                 if (dynamic_value)
1534d93b8cdSEnrico Granata                     m_valobj = dynamic_value;
1544d93b8cdSEnrico Granata                 else
1554d93b8cdSEnrico Granata                     m_valobj = m_orig_valobj;
1564d93b8cdSEnrico Granata             }
1574d93b8cdSEnrico Granata             else
1584d93b8cdSEnrico Granata                 m_valobj = m_orig_valobj;
159106260c5SEnrico Granata         }
160d07cfd3aSEnrico Granata 
161d07cfd3aSEnrico Granata         if (m_valobj->IsSynthetic())
162d07cfd3aSEnrico Granata         {
163d07cfd3aSEnrico Granata             if (options.m_use_synthetic == false)
164d07cfd3aSEnrico Granata             {
165d07cfd3aSEnrico Granata                 ValueObject *non_synthetic = m_valobj->GetNonSyntheticValue().get();
166d07cfd3aSEnrico Granata                 if (non_synthetic)
167d07cfd3aSEnrico Granata                     m_valobj = non_synthetic;
168d07cfd3aSEnrico Granata             }
169d07cfd3aSEnrico Granata         }
170d07cfd3aSEnrico Granata         else
171d07cfd3aSEnrico Granata         {
172d07cfd3aSEnrico Granata             if (options.m_use_synthetic == true)
173d07cfd3aSEnrico Granata             {
174d07cfd3aSEnrico Granata                 ValueObject *synthetic = m_valobj->GetSyntheticValue().get();
175d07cfd3aSEnrico Granata                 if (synthetic)
176d07cfd3aSEnrico Granata                     m_valobj = synthetic;
177d07cfd3aSEnrico Granata             }
178d07cfd3aSEnrico Granata         }
179106260c5SEnrico Granata     }
18059b5a37dSBruce Mitchener     m_compiler_type = m_valobj->GetCompilerType();
18159b5a37dSBruce Mitchener     m_type_flags = m_compiler_type.GetTypeInfo ();
1824d93b8cdSEnrico Granata     return true;
1834d93b8cdSEnrico Granata }
1844d93b8cdSEnrico Granata 
1854d93b8cdSEnrico Granata const char*
1864d93b8cdSEnrico Granata ValueObjectPrinter::GetDescriptionForDisplay ()
1874d93b8cdSEnrico Granata {
1884d93b8cdSEnrico Granata     const char* str = m_valobj->GetObjectDescription();
1894d93b8cdSEnrico Granata     if (!str)
1904d93b8cdSEnrico Granata         str = m_valobj->GetSummaryAsCString();
1914d93b8cdSEnrico Granata     if (!str)
1924d93b8cdSEnrico Granata         str = m_valobj->GetValueAsCString();
1934d93b8cdSEnrico Granata     return str;
1944d93b8cdSEnrico Granata }
1954d93b8cdSEnrico Granata 
1964d93b8cdSEnrico Granata const char*
1974d93b8cdSEnrico Granata ValueObjectPrinter::GetRootNameForDisplay (const char* if_fail)
1984d93b8cdSEnrico Granata {
1994d93b8cdSEnrico Granata     const char *root_valobj_name = options.m_root_valobj_name.empty() ?
2004d93b8cdSEnrico Granata         m_valobj->GetName().AsCString() :
2014d93b8cdSEnrico Granata         options.m_root_valobj_name.c_str();
2024d93b8cdSEnrico Granata     return root_valobj_name ? root_valobj_name : if_fail;
2034d93b8cdSEnrico Granata }
2044d93b8cdSEnrico Granata 
2054d93b8cdSEnrico Granata bool
2064d93b8cdSEnrico Granata ValueObjectPrinter::ShouldPrintValueObject ()
2074d93b8cdSEnrico Granata {
2084d93b8cdSEnrico Granata     if (m_should_print == eLazyBoolCalculate)
209622be238SEnrico Granata         m_should_print = (options.m_flat_output == false || m_type_flags.Test (eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo;
2104d93b8cdSEnrico Granata     return m_should_print == eLazyBoolYes;
2114d93b8cdSEnrico Granata }
2124d93b8cdSEnrico Granata 
2134d93b8cdSEnrico Granata bool
2144d93b8cdSEnrico Granata ValueObjectPrinter::IsNil ()
2154d93b8cdSEnrico Granata {
2164d93b8cdSEnrico Granata     if (m_is_nil == eLazyBoolCalculate)
2174d93b8cdSEnrico Granata         m_is_nil = m_valobj->IsObjCNil() ? eLazyBoolYes : eLazyBoolNo;
2184d93b8cdSEnrico Granata     return m_is_nil == eLazyBoolYes;
2194d93b8cdSEnrico Granata }
2204d93b8cdSEnrico Granata 
2214d93b8cdSEnrico Granata bool
2224d93b8cdSEnrico Granata ValueObjectPrinter::IsPtr ()
2234d93b8cdSEnrico Granata {
2244d93b8cdSEnrico Granata     if (m_is_ptr == eLazyBoolCalculate)
225622be238SEnrico Granata         m_is_ptr = m_type_flags.Test (eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo;
2264d93b8cdSEnrico Granata     return m_is_ptr == eLazyBoolYes;
2274d93b8cdSEnrico Granata }
2284d93b8cdSEnrico Granata 
2294d93b8cdSEnrico Granata bool
2304d93b8cdSEnrico Granata ValueObjectPrinter::IsRef ()
2314d93b8cdSEnrico Granata {
2324d93b8cdSEnrico Granata     if (m_is_ref == eLazyBoolCalculate)
233622be238SEnrico Granata         m_is_ref = m_type_flags.Test (eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo;
2344d93b8cdSEnrico Granata     return m_is_ref == eLazyBoolYes;
2354d93b8cdSEnrico Granata }
2364d93b8cdSEnrico Granata 
2374d93b8cdSEnrico Granata bool
2384d93b8cdSEnrico Granata ValueObjectPrinter::IsAggregate ()
2394d93b8cdSEnrico Granata {
2404d93b8cdSEnrico Granata     if (m_is_aggregate == eLazyBoolCalculate)
241622be238SEnrico Granata         m_is_aggregate = m_type_flags.Test (eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo;
2424d93b8cdSEnrico Granata     return m_is_aggregate == eLazyBoolYes;
2434d93b8cdSEnrico Granata }
2444d93b8cdSEnrico Granata 
2454d93b8cdSEnrico Granata bool
2464d93b8cdSEnrico Granata ValueObjectPrinter::PrintLocationIfNeeded ()
2474d93b8cdSEnrico Granata {
2484d93b8cdSEnrico Granata     if (options.m_show_location)
2494d93b8cdSEnrico Granata     {
2504d93b8cdSEnrico Granata         m_stream->Printf("%s: ", m_valobj->GetLocationAsCString());
2514d93b8cdSEnrico Granata         return true;
2524d93b8cdSEnrico Granata     }
2534d93b8cdSEnrico Granata     return false;
2544d93b8cdSEnrico Granata }
2554d93b8cdSEnrico Granata 
2564d93b8cdSEnrico Granata bool
2574d93b8cdSEnrico Granata ValueObjectPrinter::PrintTypeIfNeeded ()
2584d93b8cdSEnrico Granata {
2594d93b8cdSEnrico Granata     bool show_type = true;
2604d93b8cdSEnrico Granata     // if we are at the root-level and been asked to hide the root's type, then hide it
2614d93b8cdSEnrico Granata     if (m_curr_depth == 0 && options.m_hide_root_type)
2624d93b8cdSEnrico Granata         show_type = false;
2634d93b8cdSEnrico Granata     else
2644d93b8cdSEnrico Granata         // otherwise decide according to the usual rules (asked to show types - always at the root level)
2654d93b8cdSEnrico Granata         show_type = options.m_show_types || (m_curr_depth == 0 && !options.m_flat_output);
2664d93b8cdSEnrico Granata 
2674d93b8cdSEnrico Granata     if (show_type)
2684d93b8cdSEnrico Granata     {
2694d93b8cdSEnrico Granata         // Some ValueObjects don't have types (like registers sets). Only print
2704d93b8cdSEnrico Granata         // the type if there is one to print
271a126e462SEnrico Granata         ConstString type_name;
272a126e462SEnrico Granata         if (options.m_use_type_display_name)
273a126e462SEnrico Granata             type_name = m_valobj->GetDisplayTypeName();
274e8daa2f8SEnrico Granata         else
275a126e462SEnrico Granata             type_name = m_valobj->GetQualifiedTypeName();
276a126e462SEnrico Granata         if (type_name)
277a126e462SEnrico Granata             m_stream->Printf("(%s) ", type_name.GetCString());
2784d93b8cdSEnrico Granata         else
2794d93b8cdSEnrico Granata             show_type = false;
2804d93b8cdSEnrico Granata     }
2814d93b8cdSEnrico Granata     return show_type;
2824d93b8cdSEnrico Granata }
2834d93b8cdSEnrico Granata 
2844d93b8cdSEnrico Granata bool
2854d93b8cdSEnrico Granata ValueObjectPrinter::PrintNameIfNeeded (bool show_type)
2864d93b8cdSEnrico Granata {
2874d93b8cdSEnrico Granata     if (options.m_flat_output)
2884d93b8cdSEnrico Granata     {
2894d93b8cdSEnrico Granata         // If we are showing types, also qualify the C++ base classes
2904d93b8cdSEnrico Granata         const bool qualify_cxx_base_classes = show_type;
2914d93b8cdSEnrico Granata         if (!options.m_hide_name)
2924d93b8cdSEnrico Granata         {
2934d93b8cdSEnrico Granata             m_valobj->GetExpressionPath(*m_stream, qualify_cxx_base_classes);
2944d93b8cdSEnrico Granata             m_stream->PutCString(" =");
2954d93b8cdSEnrico Granata             return true;
2964d93b8cdSEnrico Granata         }
2974d93b8cdSEnrico Granata     }
2984d93b8cdSEnrico Granata     else if (!options.m_hide_name)
2994d93b8cdSEnrico Granata     {
3004d93b8cdSEnrico Granata         const char *name_cstr = GetRootNameForDisplay("");
3014d93b8cdSEnrico Granata         m_stream->Printf ("%s =", name_cstr);
3024d93b8cdSEnrico Granata         return true;
3034d93b8cdSEnrico Granata     }
3044d93b8cdSEnrico Granata     return false;
3054d93b8cdSEnrico Granata }
3064d93b8cdSEnrico Granata 
3074d93b8cdSEnrico Granata bool
3084d93b8cdSEnrico Granata ValueObjectPrinter::CheckScopeIfNeeded ()
3094d93b8cdSEnrico Granata {
3104d93b8cdSEnrico Granata     if (options.m_scope_already_checked)
3114d93b8cdSEnrico Granata         return true;
3124d93b8cdSEnrico Granata     return m_valobj->IsInScope();
3134d93b8cdSEnrico Granata }
3144d93b8cdSEnrico Granata 
3154d93b8cdSEnrico Granata TypeSummaryImpl*
3164d93b8cdSEnrico Granata ValueObjectPrinter::GetSummaryFormatter ()
3174d93b8cdSEnrico Granata {
3184d93b8cdSEnrico Granata     if (m_summary_formatter.second == false)
3194d93b8cdSEnrico Granata     {
3204d93b8cdSEnrico Granata         TypeSummaryImpl* entry = options.m_summary_sp ? options.m_summary_sp.get() : m_valobj->GetSummaryFormat().get();
3214d93b8cdSEnrico Granata 
3224d93b8cdSEnrico Granata         if (options.m_omit_summary_depth > 0)
3234d93b8cdSEnrico Granata             entry = NULL;
3244d93b8cdSEnrico Granata         m_summary_formatter.first = entry;
3254d93b8cdSEnrico Granata         m_summary_formatter.second = true;
3264d93b8cdSEnrico Granata     }
3274d93b8cdSEnrico Granata     return m_summary_formatter.first;
3284d93b8cdSEnrico Granata }
3294d93b8cdSEnrico Granata 
3304d93b8cdSEnrico Granata void
3314d93b8cdSEnrico Granata ValueObjectPrinter::GetValueSummaryError (std::string& value,
3324d93b8cdSEnrico Granata                                           std::string& summary,
3334d93b8cdSEnrico Granata                                           std::string& error)
3344d93b8cdSEnrico Granata {
335465f4bc2SEnrico Granata     if (options.m_format != eFormatDefault && options.m_format != m_valobj->GetFormat())
3364d93b8cdSEnrico Granata     {
337465f4bc2SEnrico Granata         m_valobj->GetValueAsCString(options.m_format,
338465f4bc2SEnrico Granata                                     value);
3394d93b8cdSEnrico Granata     }
340465f4bc2SEnrico Granata     else
341465f4bc2SEnrico Granata     {
3424d93b8cdSEnrico Granata         const char* val_cstr = m_valobj->GetValueAsCString();
343465f4bc2SEnrico Granata         if (val_cstr)
344465f4bc2SEnrico Granata             value.assign(val_cstr);
345465f4bc2SEnrico Granata     }
3464d93b8cdSEnrico Granata     const char* err_cstr = m_valobj->GetError().AsCString();
3474d93b8cdSEnrico Granata     if (err_cstr)
3484d93b8cdSEnrico Granata         error.assign(err_cstr);
3494d93b8cdSEnrico Granata 
3504d93b8cdSEnrico Granata     if (ShouldPrintValueObject())
3514d93b8cdSEnrico Granata     {
3524d93b8cdSEnrico Granata         if (IsNil())
3534d93b8cdSEnrico Granata             summary.assign("nil");
3544d93b8cdSEnrico Granata         else if (options.m_omit_summary_depth == 0)
3554d93b8cdSEnrico Granata         {
3564d93b8cdSEnrico Granata             TypeSummaryImpl* entry = GetSummaryFormatter();
3574d93b8cdSEnrico Granata             if (entry)
358*73e8c4d0SEnrico Granata                 m_valobj->GetSummaryAsCString(entry, summary, options.m_varformat_language);
3594d93b8cdSEnrico Granata             else
3604d93b8cdSEnrico Granata             {
361*73e8c4d0SEnrico Granata                 const char* sum_cstr = m_valobj->GetSummaryAsCString(options.m_varformat_language);
3624d93b8cdSEnrico Granata                 if (sum_cstr)
3634d93b8cdSEnrico Granata                     summary.assign(sum_cstr);
3644d93b8cdSEnrico Granata             }
3654d93b8cdSEnrico Granata         }
3664d93b8cdSEnrico Granata     }
3674d93b8cdSEnrico Granata }
3684d93b8cdSEnrico Granata 
3694d93b8cdSEnrico Granata bool
3704d93b8cdSEnrico Granata ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed,
3714d93b8cdSEnrico Granata                                                   bool& summary_printed)
3724d93b8cdSEnrico Granata {
3734d93b8cdSEnrico Granata     bool error_printed = false;
3744d93b8cdSEnrico Granata     if (ShouldPrintValueObject())
3754d93b8cdSEnrico Granata     {
3764d93b8cdSEnrico Granata         if (!CheckScopeIfNeeded())
3774d93b8cdSEnrico Granata             m_error.assign("out of scope");
3784d93b8cdSEnrico Granata         if (m_error.empty())
3794d93b8cdSEnrico Granata         {
3804d93b8cdSEnrico Granata             GetValueSummaryError(m_value, m_summary, m_error);
3814d93b8cdSEnrico Granata         }
3824d93b8cdSEnrico Granata         if (m_error.size())
3834d93b8cdSEnrico Granata         {
3844d93b8cdSEnrico Granata             error_printed = true;
3854d93b8cdSEnrico Granata             m_stream->Printf (" <%s>\n", m_error.c_str());
3864d93b8cdSEnrico Granata         }
3874d93b8cdSEnrico Granata         else
3884d93b8cdSEnrico Granata         {
3894d93b8cdSEnrico Granata             // Make sure we have a value and make sure the summary didn't
3904d93b8cdSEnrico Granata             // specify that the value should not be printed - and do not print
3914d93b8cdSEnrico Granata             // the value if this thing is nil
3924d93b8cdSEnrico Granata             // (but show the value if the user passes a format explicitly)
3934d93b8cdSEnrico Granata             TypeSummaryImpl* entry = GetSummaryFormatter();
3948a068e6cSEnrico Granata             if (!IsNil() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue(m_valobj) || options.m_format != eFormatDefault) || m_summary.empty()) && !options.m_hide_value)
3954d93b8cdSEnrico Granata             {
3964d93b8cdSEnrico Granata                 m_stream->Printf(" %s", m_value.c_str());
3974d93b8cdSEnrico Granata                 value_printed = true;
3984d93b8cdSEnrico Granata             }
3994d93b8cdSEnrico Granata 
4004d93b8cdSEnrico Granata             if (m_summary.size())
4014d93b8cdSEnrico Granata             {
4024d93b8cdSEnrico Granata                 m_stream->Printf(" %s", m_summary.c_str());
4034d93b8cdSEnrico Granata                 summary_printed = true;
4044d93b8cdSEnrico Granata             }
4054d93b8cdSEnrico Granata         }
4064d93b8cdSEnrico Granata     }
4074d93b8cdSEnrico Granata     return !error_printed;
4084d93b8cdSEnrico Granata }
4094d93b8cdSEnrico Granata 
4104d93b8cdSEnrico Granata bool
4114d93b8cdSEnrico Granata ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed,
4124d93b8cdSEnrico Granata                                                     bool summary_printed)
4134d93b8cdSEnrico Granata {
4144d93b8cdSEnrico Granata     if (ShouldPrintValueObject())
4154d93b8cdSEnrico Granata     {
4164d93b8cdSEnrico Granata         // let's avoid the overly verbose no description error for a nil thing
4174d93b8cdSEnrico Granata         if (options.m_use_objc && !IsNil())
4184d93b8cdSEnrico Granata         {
4194d93b8cdSEnrico Granata             if (!options.m_hide_value || !options.m_hide_name)
4204d93b8cdSEnrico Granata                 m_stream->Printf(" ");
4214d93b8cdSEnrico Granata             const char *object_desc = nullptr;
4224d93b8cdSEnrico Granata             if (value_printed || summary_printed)
4234d93b8cdSEnrico Granata                 object_desc = m_valobj->GetObjectDescription();
4244d93b8cdSEnrico Granata             else
4254d93b8cdSEnrico Granata                 object_desc = GetDescriptionForDisplay();
4264d93b8cdSEnrico Granata             if (object_desc && *object_desc)
4274d93b8cdSEnrico Granata             {
4284d93b8cdSEnrico Granata                 m_stream->Printf("%s\n", object_desc);
4294d93b8cdSEnrico Granata                 return true;
4304d93b8cdSEnrico Granata             }
4314d93b8cdSEnrico Granata             else if (value_printed == false && summary_printed == false)
4324d93b8cdSEnrico Granata                 return true;
4334d93b8cdSEnrico Granata             else
4344d93b8cdSEnrico Granata                 return false;
4354d93b8cdSEnrico Granata         }
4364d93b8cdSEnrico Granata     }
4374d93b8cdSEnrico Granata     return true;
4384d93b8cdSEnrico Granata }
4394d93b8cdSEnrico Granata 
4404d93b8cdSEnrico Granata bool
441c1b7c09aSEnrico Granata DumpValueObjectOptions::PointerDepth::CanAllowExpansion (bool is_root,
442c1b7c09aSEnrico Granata                                                          TypeSummaryImpl* entry,
443c1b7c09aSEnrico Granata                                                          ValueObject *valobj,
444c1b7c09aSEnrico Granata                                                          const std::string& summary)
445c1b7c09aSEnrico Granata {
446c1b7c09aSEnrico Granata     switch (m_mode)
447c1b7c09aSEnrico Granata     {
448c1b7c09aSEnrico Granata         case Mode::Always:
449c1b7c09aSEnrico Granata             return (m_count > 0);
450c1b7c09aSEnrico Granata         case Mode::Never:
451c1b7c09aSEnrico Granata             return false;
452c1b7c09aSEnrico Granata         case Mode::Default:
453c1b7c09aSEnrico Granata             if (is_root)
454c1b7c09aSEnrico Granata                 m_count = std::min<decltype(m_count)>(m_count,1);
455c1b7c09aSEnrico Granata             return m_count > 0;
456c1b7c09aSEnrico Granata         case Mode::Formatters:
457c1b7c09aSEnrico Granata             if (!entry || entry->DoesPrintChildren(valobj) || summary.empty())
458c1b7c09aSEnrico Granata                 return m_count > 0;
459c1b7c09aSEnrico Granata             return false;
460c1b7c09aSEnrico Granata     }
46184f5b0dfSZachary Turner     return false;
462c1b7c09aSEnrico Granata }
463c1b7c09aSEnrico Granata 
464c1b7c09aSEnrico Granata bool
465c1b7c09aSEnrico Granata DumpValueObjectOptions::PointerDepth::CanAllowExpansion () const
466c1b7c09aSEnrico Granata {
467c1b7c09aSEnrico Granata     switch (m_mode)
468c1b7c09aSEnrico Granata     {
469c1b7c09aSEnrico Granata         case Mode::Always:
470c1b7c09aSEnrico Granata         case Mode::Default:
471c1b7c09aSEnrico Granata         case Mode::Formatters:
472c1b7c09aSEnrico Granata             return (m_count > 0);
473c1b7c09aSEnrico Granata         case Mode::Never:
474c1b7c09aSEnrico Granata             return false;
475c1b7c09aSEnrico Granata     }
47684f5b0dfSZachary Turner     return false;
477c1b7c09aSEnrico Granata }
478c1b7c09aSEnrico Granata 
479c1b7c09aSEnrico Granata bool
4804d93b8cdSEnrico Granata ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description,
481c1b7c09aSEnrico Granata                                          DumpValueObjectOptions::PointerDepth& curr_ptr_depth)
4824d93b8cdSEnrico Granata {
4834d93b8cdSEnrico Granata     const bool is_ref = IsRef ();
4844d93b8cdSEnrico Granata     const bool is_ptr = IsPtr ();
4854d93b8cdSEnrico Granata 
486c1b7c09aSEnrico Granata     TypeSummaryImpl* entry = GetSummaryFormatter();
487c1b7c09aSEnrico Granata 
4884d93b8cdSEnrico Granata     if (is_failed_description || m_curr_depth < options.m_max_depth)
4894d93b8cdSEnrico Granata     {
4904d93b8cdSEnrico Granata         // We will show children for all concrete types. We won't show
4914d93b8cdSEnrico Granata         // pointer contents unless a pointer depth has been specified.
4924d93b8cdSEnrico Granata         // We won't reference contents unless the reference is the
4934d93b8cdSEnrico Granata         // root object (depth of zero).
4944d93b8cdSEnrico Granata 
4954d93b8cdSEnrico Granata         // Use a new temporary pointer depth in case we override the
4964d93b8cdSEnrico Granata         // current pointer depth below...
4974d93b8cdSEnrico Granata 
4984d93b8cdSEnrico Granata         if (is_ptr || is_ref)
4994d93b8cdSEnrico Granata         {
5004d93b8cdSEnrico Granata             // We have a pointer or reference whose value is an address.
5014d93b8cdSEnrico Granata             // Make sure that address is not NULL
5024d93b8cdSEnrico Granata             AddressType ptr_address_type;
5034d93b8cdSEnrico Granata             if (m_valobj->GetPointerValue (&ptr_address_type) == 0)
5044d93b8cdSEnrico Granata                 return false;
5054d93b8cdSEnrico Granata 
506c1b7c09aSEnrico Granata             const bool is_root_level = m_curr_depth == 0;
507c1b7c09aSEnrico Granata 
508c1b7c09aSEnrico Granata             if (is_ref &&
509c1b7c09aSEnrico Granata                 is_root_level)
5104d93b8cdSEnrico Granata             {
5114d93b8cdSEnrico Granata                 // If this is the root object (depth is zero) that we are showing
5124d93b8cdSEnrico Granata                 // and it is a reference, and no pointer depth has been supplied
5134d93b8cdSEnrico Granata                 // print out what it references. Don't do this at deeper depths
5144d93b8cdSEnrico Granata                 // otherwise we can end up with infinite recursion...
515c1b7c09aSEnrico Granata                 return true;
5164d93b8cdSEnrico Granata             }
5174d93b8cdSEnrico Granata 
518c1b7c09aSEnrico Granata             return curr_ptr_depth.CanAllowExpansion(false, entry, m_valobj, m_summary);
5194d93b8cdSEnrico Granata         }
5204d93b8cdSEnrico Granata 
5218a068e6cSEnrico Granata         return (!entry || entry->DoesPrintChildren(m_valobj) || m_summary.empty());
5224d93b8cdSEnrico Granata     }
5234d93b8cdSEnrico Granata     return false;
5244d93b8cdSEnrico Granata }
5254d93b8cdSEnrico Granata 
526d26eb907SSiva Chandra bool
527d26eb907SSiva Chandra ValueObjectPrinter::ShouldExpandEmptyAggregates ()
528d26eb907SSiva Chandra {
529d26eb907SSiva Chandra     TypeSummaryImpl* entry = GetSummaryFormatter();
530d26eb907SSiva Chandra 
531d26eb907SSiva Chandra     if (!entry)
532d26eb907SSiva Chandra         return true;
533d26eb907SSiva Chandra 
534d26eb907SSiva Chandra     return entry->DoesPrintEmptyAggregates();
535d26eb907SSiva Chandra }
536d26eb907SSiva Chandra 
5374d93b8cdSEnrico Granata ValueObject*
5384d93b8cdSEnrico Granata ValueObjectPrinter::GetValueObjectForChildrenGeneration ()
5394d93b8cdSEnrico Granata {
540d07cfd3aSEnrico Granata     return m_valobj;
5414d93b8cdSEnrico Granata }
5424d93b8cdSEnrico Granata 
5434d93b8cdSEnrico Granata void
5444d93b8cdSEnrico Granata ValueObjectPrinter::PrintChildrenPreamble ()
5454d93b8cdSEnrico Granata {
5464d93b8cdSEnrico Granata     if (options.m_flat_output)
5474d93b8cdSEnrico Granata     {
5484d93b8cdSEnrico Granata         if (ShouldPrintValueObject())
5494d93b8cdSEnrico Granata             m_stream->EOL();
5504d93b8cdSEnrico Granata     }
5514d93b8cdSEnrico Granata     else
5524d93b8cdSEnrico Granata     {
5534d93b8cdSEnrico Granata         if (ShouldPrintValueObject())
5544d93b8cdSEnrico Granata             m_stream->PutCString(IsRef () ? ": {\n" : " {\n");
5554d93b8cdSEnrico Granata         m_stream->IndentMore();
5564d93b8cdSEnrico Granata     }
5574d93b8cdSEnrico Granata }
5584d93b8cdSEnrico Granata 
5594d93b8cdSEnrico Granata void
5604d93b8cdSEnrico Granata ValueObjectPrinter::PrintChild (ValueObjectSP child_sp,
561c1b7c09aSEnrico Granata                                 const DumpValueObjectOptions::PointerDepth& curr_ptr_depth)
5624d93b8cdSEnrico Granata {
5634d93b8cdSEnrico Granata     DumpValueObjectOptions child_options(options);
564443844c4SEnrico Granata     child_options.SetFormat(options.m_format).SetSummary().SetRootValueObjectName();
5654d93b8cdSEnrico Granata     child_options.SetScopeChecked(true).SetHideName(options.m_hide_name).SetHideValue(options.m_hide_value)
5664d93b8cdSEnrico Granata     .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0);
5674d93b8cdSEnrico Granata     if (child_sp.get())
5684d93b8cdSEnrico Granata     {
5694d93b8cdSEnrico Granata         ValueObjectPrinter child_printer(child_sp.get(),
5704d93b8cdSEnrico Granata                                          m_stream,
5714d93b8cdSEnrico Granata                                          child_options,
572c1b7c09aSEnrico Granata                                          (IsPtr() || IsRef()) ? --curr_ptr_depth : curr_ptr_depth,
5734d93b8cdSEnrico Granata                                          m_curr_depth + 1);
5744d93b8cdSEnrico Granata         child_printer.PrintValueObject();
5754d93b8cdSEnrico Granata     }
5764d93b8cdSEnrico Granata }
5774d93b8cdSEnrico Granata 
5784d93b8cdSEnrico Granata uint32_t
5794d93b8cdSEnrico Granata ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot)
5804d93b8cdSEnrico Granata {
5814d93b8cdSEnrico Granata     ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
5824d93b8cdSEnrico Granata 
5834d93b8cdSEnrico Granata     size_t num_children = synth_m_valobj->GetNumChildren();
5844d93b8cdSEnrico Granata     print_dotdotdot = false;
5854d93b8cdSEnrico Granata     if (num_children)
5864d93b8cdSEnrico Granata     {
5874d93b8cdSEnrico Granata         const size_t max_num_children = m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
5884d93b8cdSEnrico Granata 
5894d93b8cdSEnrico Granata         if (num_children > max_num_children && !options.m_ignore_cap)
5904d93b8cdSEnrico Granata         {
5914d93b8cdSEnrico Granata             print_dotdotdot = true;
5924d93b8cdSEnrico Granata             return max_num_children;
5934d93b8cdSEnrico Granata         }
5944d93b8cdSEnrico Granata     }
5954d93b8cdSEnrico Granata     return num_children;
5964d93b8cdSEnrico Granata }
5974d93b8cdSEnrico Granata 
5984d93b8cdSEnrico Granata void
5994d93b8cdSEnrico Granata ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot)
6004d93b8cdSEnrico Granata {
6014d93b8cdSEnrico Granata     if (!options.m_flat_output)
6024d93b8cdSEnrico Granata     {
6034d93b8cdSEnrico Granata         if (print_dotdotdot)
6044d93b8cdSEnrico Granata         {
6054d93b8cdSEnrico Granata             m_valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().ChildrenTruncated();
6064d93b8cdSEnrico Granata             m_stream->Indent("...\n");
6074d93b8cdSEnrico Granata         }
6084d93b8cdSEnrico Granata         m_stream->IndentLess();
6094d93b8cdSEnrico Granata         m_stream->Indent("}\n");
6104d93b8cdSEnrico Granata     }
6114d93b8cdSEnrico Granata }
6124d93b8cdSEnrico Granata 
6134d93b8cdSEnrico Granata void
614c1b7c09aSEnrico Granata ValueObjectPrinter::PrintChildren (bool value_printed,
615c1b7c09aSEnrico Granata                                    bool summary_printed,
616c1b7c09aSEnrico Granata                                    const DumpValueObjectOptions::PointerDepth& curr_ptr_depth)
6174d93b8cdSEnrico Granata {
6184d93b8cdSEnrico Granata     ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
6194d93b8cdSEnrico Granata 
6204d93b8cdSEnrico Granata     bool print_dotdotdot = false;
6214d93b8cdSEnrico Granata     size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
6224d93b8cdSEnrico Granata     if (num_children)
6234d93b8cdSEnrico Granata     {
6244d93b8cdSEnrico Granata         PrintChildrenPreamble ();
6254d93b8cdSEnrico Granata 
6264d93b8cdSEnrico Granata         for (size_t idx=0; idx<num_children; ++idx)
6274d93b8cdSEnrico Granata         {
6284d93b8cdSEnrico Granata             ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
6294d93b8cdSEnrico Granata             PrintChild (child_sp, curr_ptr_depth);
6304d93b8cdSEnrico Granata         }
6314d93b8cdSEnrico Granata 
6324d93b8cdSEnrico Granata         PrintChildrenPostamble (print_dotdotdot);
6334d93b8cdSEnrico Granata     }
6344d93b8cdSEnrico Granata     else if (IsAggregate())
6354d93b8cdSEnrico Granata     {
6364d93b8cdSEnrico Granata         // Aggregate, no children...
6374d93b8cdSEnrico Granata         if (ShouldPrintValueObject())
638d07cfd3aSEnrico Granata         {
639d07cfd3aSEnrico Granata             // if it has a synthetic value, then don't print {}, the synthetic children are probably only being used to vend a value
640d26eb907SSiva Chandra             if (m_valobj->DoesProvideSyntheticValue() || !ShouldExpandEmptyAggregates())
641d07cfd3aSEnrico Granata                 m_stream->PutCString( "\n");
642d07cfd3aSEnrico Granata             else
6434d93b8cdSEnrico Granata                 m_stream->PutCString(" {}\n");
6444d93b8cdSEnrico Granata         }
645d07cfd3aSEnrico Granata     }
6464d93b8cdSEnrico Granata     else
6474d93b8cdSEnrico Granata     {
6484d93b8cdSEnrico Granata         if (ShouldPrintValueObject())
6494d93b8cdSEnrico Granata             m_stream->EOL();
6504d93b8cdSEnrico Granata     }
6514d93b8cdSEnrico Granata }
6524d93b8cdSEnrico Granata 
653a29cb0baSEnrico Granata bool
654a29cb0baSEnrico Granata ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names)
655a29cb0baSEnrico Granata {
656d07cfd3aSEnrico Granata     if (!GetMostSpecializedValue () || m_valobj == nullptr)
657a29cb0baSEnrico Granata         return false;
658a29cb0baSEnrico Granata 
659a29cb0baSEnrico Granata     ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
660a29cb0baSEnrico Granata 
661a29cb0baSEnrico Granata     bool print_dotdotdot = false;
662a29cb0baSEnrico Granata     size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
663a29cb0baSEnrico Granata 
664a29cb0baSEnrico Granata     if (num_children)
665a29cb0baSEnrico Granata     {
666a29cb0baSEnrico Granata         m_stream->PutChar('(');
667a29cb0baSEnrico Granata 
668a29cb0baSEnrico Granata         for (uint32_t idx=0; idx<num_children; ++idx)
669a29cb0baSEnrico Granata         {
670a29cb0baSEnrico Granata             lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
671ddac7611SEnrico Granata             if (child_sp)
672ddac7611SEnrico Granata                 child_sp = child_sp->GetQualifiedRepresentationIfAvailable(options.m_use_dynamic, options.m_use_synthetic);
673a29cb0baSEnrico Granata             if (child_sp)
674a29cb0baSEnrico Granata             {
675a29cb0baSEnrico Granata                 if (idx)
676a29cb0baSEnrico Granata                     m_stream->PutCString(", ");
677a29cb0baSEnrico Granata                 if (!hide_names)
678a29cb0baSEnrico Granata                 {
679a29cb0baSEnrico Granata                     const char* name = child_sp.get()->GetName().AsCString();
680a29cb0baSEnrico Granata                     if (name && *name)
681a29cb0baSEnrico Granata                     {
682a29cb0baSEnrico Granata                         m_stream->PutCString(name);
683a29cb0baSEnrico Granata                         m_stream->PutCString(" = ");
684a29cb0baSEnrico Granata                     }
685a29cb0baSEnrico Granata                 }
686a29cb0baSEnrico Granata                 child_sp->DumpPrintableRepresentation(*m_stream,
687a29cb0baSEnrico Granata                                                       ValueObject::eValueObjectRepresentationStyleSummary,
688443844c4SEnrico Granata                                                       lldb::eFormatInvalid,
689a29cb0baSEnrico Granata                                                       ValueObject::ePrintableRepresentationSpecialCasesDisable);
690a29cb0baSEnrico Granata             }
691a29cb0baSEnrico Granata         }
692a29cb0baSEnrico Granata 
693a29cb0baSEnrico Granata         if (print_dotdotdot)
694a29cb0baSEnrico Granata             m_stream->PutCString(", ...)");
695a29cb0baSEnrico Granata         else
696a29cb0baSEnrico Granata             m_stream->PutChar(')');
697a29cb0baSEnrico Granata     }
698a29cb0baSEnrico Granata     return true;
699a29cb0baSEnrico Granata }
700a29cb0baSEnrico Granata 
7014d93b8cdSEnrico Granata void
7024d93b8cdSEnrico Granata ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed,
7034d93b8cdSEnrico Granata                                            bool summary_printed)
7044d93b8cdSEnrico Granata {
7054d93b8cdSEnrico Granata     // this flag controls whether we tried to display a description for this object and failed
7064d93b8cdSEnrico Granata     // if that happens, we want to display the children, if any
7074d93b8cdSEnrico Granata     bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed);
7084d93b8cdSEnrico Granata 
709c1b7c09aSEnrico Granata     auto curr_ptr_depth = m_ptr_depth;
7104d93b8cdSEnrico Granata     bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth);
711c1b7c09aSEnrico Granata     bool print_oneline = (curr_ptr_depth.CanAllowExpansion() ||
7123fa6dc90SEnrico Granata                           options.m_show_types ||
7133fa6dc90SEnrico Granata                           !options.m_allow_oneliner_mode ||
7143fa6dc90SEnrico Granata                           options.m_flat_output ||
7153fa6dc90SEnrico Granata                           options.m_show_location) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj);
7164d93b8cdSEnrico Granata 
7174d93b8cdSEnrico Granata     if (print_children)
7184d93b8cdSEnrico Granata     {
719a29cb0baSEnrico Granata         if (print_oneline)
720a29cb0baSEnrico Granata         {
721a29cb0baSEnrico Granata             m_stream->PutChar(' ');
722a29cb0baSEnrico Granata             PrintChildrenOneLiner (false);
723a29cb0baSEnrico Granata             m_stream->EOL();
724a29cb0baSEnrico Granata         }
725a29cb0baSEnrico Granata         else
726c1b7c09aSEnrico Granata             PrintChildren (value_printed, summary_printed, curr_ptr_depth);
7274d93b8cdSEnrico Granata     }
7284d93b8cdSEnrico Granata     else if (m_curr_depth >= options.m_max_depth && IsAggregate() && ShouldPrintValueObject())
7294d93b8cdSEnrico Granata     {
7304d93b8cdSEnrico Granata             m_stream->PutCString("{...}\n");
7314d93b8cdSEnrico Granata     }
732245b3caaSEnrico Granata     else
733245b3caaSEnrico Granata         m_stream->EOL();
7344d93b8cdSEnrico Granata }
7350f883ffbSEnrico Granata 
7360f883ffbSEnrico Granata bool
7370f883ffbSEnrico Granata ValueObjectPrinter::ShouldPrintValidation ()
7380f883ffbSEnrico Granata {
7390f883ffbSEnrico Granata     return options.m_run_validator;
7400f883ffbSEnrico Granata }
7410f883ffbSEnrico Granata 
7420f883ffbSEnrico Granata bool
7430f883ffbSEnrico Granata ValueObjectPrinter::PrintValidationMarkerIfNeeded ()
7440f883ffbSEnrico Granata {
7450f883ffbSEnrico Granata     if (!ShouldPrintValidation())
7460f883ffbSEnrico Granata         return false;
7470f883ffbSEnrico Granata 
7480f883ffbSEnrico Granata     m_validation = m_valobj->GetValidationStatus();
7490f883ffbSEnrico Granata 
7500f883ffbSEnrico Granata     if (TypeValidatorResult::Failure == m_validation.first)
7510f883ffbSEnrico Granata     {
7520f883ffbSEnrico Granata         m_stream->Printf("! ");
7530f883ffbSEnrico Granata         return true;
7540f883ffbSEnrico Granata     }
7550f883ffbSEnrico Granata 
7560f883ffbSEnrico Granata     return false;
7570f883ffbSEnrico Granata }
7580f883ffbSEnrico Granata 
7590f883ffbSEnrico Granata bool
7600f883ffbSEnrico Granata ValueObjectPrinter::PrintValidationErrorIfNeeded ()
7610f883ffbSEnrico Granata {
7620f883ffbSEnrico Granata     if (!ShouldPrintValidation())
7630f883ffbSEnrico Granata         return false;
7640f883ffbSEnrico Granata 
7650f883ffbSEnrico Granata     if (TypeValidatorResult::Success == m_validation.first)
7660f883ffbSEnrico Granata         return false;
7670f883ffbSEnrico Granata 
7680f883ffbSEnrico Granata     if (m_validation.second.empty())
7690f883ffbSEnrico Granata         m_validation.second.assign("unknown error");
7700f883ffbSEnrico Granata 
7710f883ffbSEnrico Granata     m_stream->Printf(" ! validation error: %s", m_validation.second.c_str());
7720f883ffbSEnrico Granata     m_stream->EOL();
7730f883ffbSEnrico Granata 
7740f883ffbSEnrico Granata     return true;
7750f883ffbSEnrico Granata }
776