1*554f68d3SGreg Clayton //===-- FormatEntity.cpp ----------------------------------------*- C++ -*-===//
2*554f68d3SGreg Clayton //
3*554f68d3SGreg Clayton //                     The LLVM Compiler Infrastructure
4*554f68d3SGreg Clayton //
5*554f68d3SGreg Clayton // This file is distributed under the University of Illinois Open Source
6*554f68d3SGreg Clayton // License. See LICENSE.TXT for details.
7*554f68d3SGreg Clayton //
8*554f68d3SGreg Clayton //===----------------------------------------------------------------------===//
9*554f68d3SGreg Clayton 
10*554f68d3SGreg Clayton #include "llvm/ADT/StringRef.h"
11*554f68d3SGreg Clayton 
12*554f68d3SGreg Clayton #include "lldb/Core/FormatEntity.h"
13*554f68d3SGreg Clayton 
14*554f68d3SGreg Clayton #include "lldb/Core/Address.h"
15*554f68d3SGreg Clayton #include "lldb/Core/Debugger.h"
16*554f68d3SGreg Clayton #include "lldb/Core/Module.h"
17*554f68d3SGreg Clayton #include "lldb/Core/Stream.h"
18*554f68d3SGreg Clayton #include "lldb/Core/StreamString.h"
19*554f68d3SGreg Clayton #include "lldb/Core/ValueObject.h"
20*554f68d3SGreg Clayton #include "lldb/Core/ValueObjectVariable.h"
21*554f68d3SGreg Clayton #include "lldb/DataFormatters/DataVisualization.h"
22*554f68d3SGreg Clayton #include "lldb/DataFormatters/FormatManager.h"
23*554f68d3SGreg Clayton #include "lldb/Host/FileSpec.h"
24*554f68d3SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
25*554f68d3SGreg Clayton #include "lldb/Symbol/Block.h"
26*554f68d3SGreg Clayton #include "lldb/Symbol/CompileUnit.h"
27*554f68d3SGreg Clayton #include "lldb/Symbol/Function.h"
28*554f68d3SGreg Clayton #include "lldb/Symbol/LineEntry.h"
29*554f68d3SGreg Clayton #include "lldb/Symbol/Symbol.h"
30*554f68d3SGreg Clayton #include "lldb/Symbol/VariableList.h"
31*554f68d3SGreg Clayton #include "lldb/Target/ExecutionContext.h"
32*554f68d3SGreg Clayton #include "lldb/Target/Process.h"
33*554f68d3SGreg Clayton #include "lldb/Target/RegisterContext.h"
34*554f68d3SGreg Clayton #include "lldb/Target/SectionLoadList.h"
35*554f68d3SGreg Clayton #include "lldb/Target/StackFrame.h"
36*554f68d3SGreg Clayton #include "lldb/Target/StopInfo.h"
37*554f68d3SGreg Clayton #include "lldb/Target/Target.h"
38*554f68d3SGreg Clayton #include "lldb/Target/Thread.h"
39*554f68d3SGreg Clayton #include "lldb/Utility/AnsiTerminal.h"
40*554f68d3SGreg Clayton 
41*554f68d3SGreg Clayton using namespace lldb;
42*554f68d3SGreg Clayton using namespace lldb_private;
43*554f68d3SGreg Clayton 
44*554f68d3SGreg Clayton 
45*554f68d3SGreg Clayton enum FileKind
46*554f68d3SGreg Clayton {
47*554f68d3SGreg Clayton     FileError = 0,
48*554f68d3SGreg Clayton     Basename,
49*554f68d3SGreg Clayton     Dirname,
50*554f68d3SGreg Clayton     Fullpath
51*554f68d3SGreg Clayton };
52*554f68d3SGreg Clayton 
53*554f68d3SGreg Clayton #define ENTRY(n,t,f)            { n, NULL, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0,0,NULL, false}
54*554f68d3SGreg Clayton #define ENTRY_VALUE(n,t,f,v)    { n, NULL, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, v,0,NULL, false}
55*554f68d3SGreg Clayton #define ENTRY_CHILDREN(n,t,f,c) { n, NULL, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0,llvm::array_lengthof(c),c, false}
56*554f68d3SGreg Clayton #define ENTRY_CHILDREN_KEEP_SEP(n,t,f,c) { n, NULL, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0,llvm::array_lengthof(c),c, true}
57*554f68d3SGreg Clayton #define ENTRY_STRING(n,s)       { n, s, FormatEntity::Entry::Type::InsertString, FormatEntity::Entry::FormatType::None, 0,0, NULL, false}
58*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_string_entry[] =
59*554f68d3SGreg Clayton {
60*554f68d3SGreg Clayton     ENTRY("*", ParentString, None)
61*554f68d3SGreg Clayton };
62*554f68d3SGreg Clayton 
63*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_addr_entries[] =
64*554f68d3SGreg Clayton {
65*554f68d3SGreg Clayton     ENTRY ("load", AddressLoad      , UInt64),
66*554f68d3SGreg Clayton     ENTRY ("file", AddressFile      , UInt64),
67*554f68d3SGreg Clayton     ENTRY ("load", AddressLoadOrFile, UInt64),
68*554f68d3SGreg Clayton };
69*554f68d3SGreg Clayton 
70*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_file_child_entries[] =
71*554f68d3SGreg Clayton {
72*554f68d3SGreg Clayton     ENTRY_VALUE("basename", ParentNumber, CString, FileKind::Basename),
73*554f68d3SGreg Clayton     ENTRY_VALUE("dirname", ParentNumber, CString, FileKind::Dirname),
74*554f68d3SGreg Clayton     ENTRY_VALUE("fullpath", ParentNumber, CString, FileKind::Fullpath)
75*554f68d3SGreg Clayton };
76*554f68d3SGreg Clayton 
77*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_frame_child_entries[] =
78*554f68d3SGreg Clayton {
79*554f68d3SGreg Clayton 
80*554f68d3SGreg Clayton     ENTRY ("index", FrameIndex        , UInt32),
81*554f68d3SGreg Clayton     ENTRY ("pc"   , FrameRegisterPC   , UInt64),
82*554f68d3SGreg Clayton     ENTRY ("fp"   , FrameRegisterFP   , UInt64),
83*554f68d3SGreg Clayton     ENTRY ("sp"   , FrameRegisterSP   , UInt64),
84*554f68d3SGreg Clayton     ENTRY ("flags", FrameRegisterFlags, UInt64),
85*554f68d3SGreg Clayton     ENTRY_CHILDREN ("reg", FrameRegisterByName, UInt64, g_string_entry),
86*554f68d3SGreg Clayton };
87*554f68d3SGreg Clayton 
88*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_function_child_entries[] =
89*554f68d3SGreg Clayton {
90*554f68d3SGreg Clayton     ENTRY ("id"                  , FunctionID             , UInt64),
91*554f68d3SGreg Clayton     ENTRY ("name"                , FunctionName           , CString),
92*554f68d3SGreg Clayton     ENTRY ("name-without-args"   , FunctionNameNoArgs     , CString),
93*554f68d3SGreg Clayton     ENTRY ("name-with-args"      , FunctionNameWithArgs   , CString),
94*554f68d3SGreg Clayton     ENTRY ("addr-offset"         , FunctionAddrOffset     , UInt64),
95*554f68d3SGreg Clayton     ENTRY ("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete, UInt64),
96*554f68d3SGreg Clayton     ENTRY ("line-offset"         , FunctionLineOffset     , UInt64),
97*554f68d3SGreg Clayton     ENTRY ("pc-offset"           , FunctionPCOffset       , UInt64)
98*554f68d3SGreg Clayton };
99*554f68d3SGreg Clayton 
100*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_line_child_entries[] =
101*554f68d3SGreg Clayton {
102*554f68d3SGreg Clayton     ENTRY_CHILDREN("file", LineEntryFile        , None  , g_file_child_entries),
103*554f68d3SGreg Clayton     ENTRY("number"       , LineEntryLineNumber  , UInt32),
104*554f68d3SGreg Clayton     ENTRY("start-addr"   , LineEntryStartAddress, UInt64),
105*554f68d3SGreg Clayton     ENTRY("end-addr"     , LineEntryEndAddress  , UInt64),
106*554f68d3SGreg Clayton };
107*554f68d3SGreg Clayton 
108*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_module_child_entries[] =
109*554f68d3SGreg Clayton {
110*554f68d3SGreg Clayton     ENTRY_CHILDREN("file", ModuleFile, None, g_file_child_entries),
111*554f68d3SGreg Clayton };
112*554f68d3SGreg Clayton 
113*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_process_child_entries[] =
114*554f68d3SGreg Clayton {
115*554f68d3SGreg Clayton     ENTRY           ( "id"      , ProcessID     , UInt64    ),
116*554f68d3SGreg Clayton     ENTRY_VALUE     ( "name"    , ProcessFile   , CString   , FileKind::Basename),
117*554f68d3SGreg Clayton     ENTRY_CHILDREN  ( "file"    , ProcessFile   , None      , g_file_child_entries),
118*554f68d3SGreg Clayton };
119*554f68d3SGreg Clayton 
120*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_svar_child_entries[] =
121*554f68d3SGreg Clayton {
122*554f68d3SGreg Clayton     ENTRY           ( "*"       , ParentString  , None)
123*554f68d3SGreg Clayton };
124*554f68d3SGreg Clayton 
125*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_var_child_entries[] =
126*554f68d3SGreg Clayton {
127*554f68d3SGreg Clayton     ENTRY           ( "*"       , ParentString  , None)
128*554f68d3SGreg Clayton };
129*554f68d3SGreg Clayton 
130*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_thread_child_entries[] =
131*554f68d3SGreg Clayton {
132*554f68d3SGreg Clayton     ENTRY           ( "id"                  , ThreadID                   , UInt64   ),
133*554f68d3SGreg Clayton     ENTRY           ( "protocol_id"         , ThreadProtocolID           , UInt64   ),
134*554f68d3SGreg Clayton     ENTRY           ( "index"               , ThreadIndexID              , UInt32   ),
135*554f68d3SGreg Clayton     ENTRY_CHILDREN  ( "info"                , ThreadInfo                 , None     , g_string_entry),
136*554f68d3SGreg Clayton     ENTRY           ( "queue"               , ThreadQueue                , CString  ),
137*554f68d3SGreg Clayton     ENTRY           ( "name"                , ThreadName                 , CString  ),
138*554f68d3SGreg Clayton     ENTRY           ( "stop-reason"         , ThreadStopReason           , CString  ),
139*554f68d3SGreg Clayton     ENTRY           ( "return-value"        , ThreadReturnValue          , CString  ),
140*554f68d3SGreg Clayton     ENTRY           ( "completed-expression", ThreadCompletedExpression  , CString  ),
141*554f68d3SGreg Clayton };
142*554f68d3SGreg Clayton 
143*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_target_child_entries[] =
144*554f68d3SGreg Clayton {
145*554f68d3SGreg Clayton     ENTRY           ( "arch"    , TargetArch    , CString   ),
146*554f68d3SGreg Clayton };
147*554f68d3SGreg Clayton 
148*554f68d3SGreg Clayton #define _TO_STR2(_val) #_val
149*554f68d3SGreg Clayton #define _TO_STR(_val) _TO_STR2(_val)
150*554f68d3SGreg Clayton 
151*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_ansi_fg_entries[] =
152*554f68d3SGreg Clayton {
153*554f68d3SGreg Clayton     ENTRY_STRING ("black"   , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK)      ANSI_ESC_END),
154*554f68d3SGreg Clayton     ENTRY_STRING ("red"     , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED)        ANSI_ESC_END),
155*554f68d3SGreg Clayton     ENTRY_STRING ("green"   , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN)      ANSI_ESC_END),
156*554f68d3SGreg Clayton     ENTRY_STRING ("yellow"  , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW)     ANSI_ESC_END),
157*554f68d3SGreg Clayton     ENTRY_STRING ("blue"    , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE)       ANSI_ESC_END),
158*554f68d3SGreg Clayton     ENTRY_STRING ("purple"  , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE)     ANSI_ESC_END),
159*554f68d3SGreg Clayton     ENTRY_STRING ("cyan"    , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN)       ANSI_ESC_END),
160*554f68d3SGreg Clayton     ENTRY_STRING ("white"   , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE)      ANSI_ESC_END),
161*554f68d3SGreg Clayton };
162*554f68d3SGreg Clayton 
163*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_ansi_bg_entries[] =
164*554f68d3SGreg Clayton {
165*554f68d3SGreg Clayton     ENTRY_STRING ("black"   , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK)      ANSI_ESC_END),
166*554f68d3SGreg Clayton     ENTRY_STRING ("red"     , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED)        ANSI_ESC_END),
167*554f68d3SGreg Clayton     ENTRY_STRING ("green"   , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN)      ANSI_ESC_END),
168*554f68d3SGreg Clayton     ENTRY_STRING ("yellow"  , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW)     ANSI_ESC_END),
169*554f68d3SGreg Clayton     ENTRY_STRING ("blue"    , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE)       ANSI_ESC_END),
170*554f68d3SGreg Clayton     ENTRY_STRING ("purple"  , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE)     ANSI_ESC_END),
171*554f68d3SGreg Clayton     ENTRY_STRING ("cyan"    , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN)       ANSI_ESC_END),
172*554f68d3SGreg Clayton     ENTRY_STRING ("white"   , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE)      ANSI_ESC_END),
173*554f68d3SGreg Clayton };
174*554f68d3SGreg Clayton 
175*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_ansi_entries[] =
176*554f68d3SGreg Clayton {
177*554f68d3SGreg Clayton     ENTRY_CHILDREN  ( "fg"          , Invalid  , None      , g_ansi_fg_entries),
178*554f68d3SGreg Clayton     ENTRY_CHILDREN  ( "bg"          , Invalid  , None      , g_ansi_bg_entries),
179*554f68d3SGreg Clayton     ENTRY_STRING    ( "normal"      , ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL)         ANSI_ESC_END),
180*554f68d3SGreg Clayton     ENTRY_STRING    ( "bold"        , ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD)           ANSI_ESC_END),
181*554f68d3SGreg Clayton     ENTRY_STRING    ( "faint"       , ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT)          ANSI_ESC_END),
182*554f68d3SGreg Clayton     ENTRY_STRING    ( "italic"      , ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC)         ANSI_ESC_END),
183*554f68d3SGreg Clayton     ENTRY_STRING    ( "underline"   , ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE)      ANSI_ESC_END),
184*554f68d3SGreg Clayton     ENTRY_STRING    ( "slow-blink"  , ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK)     ANSI_ESC_END),
185*554f68d3SGreg Clayton     ENTRY_STRING    ( "fast-blink"  , ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK)     ANSI_ESC_END),
186*554f68d3SGreg Clayton     ENTRY_STRING    ( "negative"    , ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END),
187*554f68d3SGreg Clayton     ENTRY_STRING    ( "conceal"     , ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL)        ANSI_ESC_END),
188*554f68d3SGreg Clayton     ENTRY_STRING    ( "crossed-out" , ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT)    ANSI_ESC_END),
189*554f68d3SGreg Clayton 
190*554f68d3SGreg Clayton };
191*554f68d3SGreg Clayton 
192*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_script_child_entries[] =
193*554f68d3SGreg Clayton {
194*554f68d3SGreg Clayton     ENTRY  ( "frame"   , ScriptFrame               , None),
195*554f68d3SGreg Clayton     ENTRY  ( "process" , ScriptProcess             , None),
196*554f68d3SGreg Clayton     ENTRY  ( "target"  , ScriptTarget              , None),
197*554f68d3SGreg Clayton     ENTRY  ( "thread"  , ScriptThread              , None),
198*554f68d3SGreg Clayton     ENTRY  ( "var"     , ScriptVariable            , None),
199*554f68d3SGreg Clayton     ENTRY  ( "svar"    , ScriptVariableSynthetic   , None),
200*554f68d3SGreg Clayton     ENTRY  ( "thread"  , ScriptThread              , None),
201*554f68d3SGreg Clayton };
202*554f68d3SGreg Clayton 
203*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_top_level_entries[] =
204*554f68d3SGreg Clayton {
205*554f68d3SGreg Clayton     ENTRY_CHILDREN          ("addr"                , AddressLoadOrFile      , UInt64    , g_addr_entries),
206*554f68d3SGreg Clayton     ENTRY                   ("addr-file-or-load"   , AddressLoadOrFile      , UInt64    ),
207*554f68d3SGreg Clayton     ENTRY_CHILDREN          ("ansi"                , Invalid                , None      , g_ansi_entries),
208*554f68d3SGreg Clayton     ENTRY                   ("current-pc-arrow"    , CurrentPCArrow         , CString   ),
209*554f68d3SGreg Clayton     ENTRY_CHILDREN          ("file"                , File                   , CString   , g_file_child_entries),
210*554f68d3SGreg Clayton     ENTRY_CHILDREN          ("frame"               , Invalid                , None      , g_frame_child_entries),
211*554f68d3SGreg Clayton     ENTRY_CHILDREN          ("function"            , Invalid                , None      , g_function_child_entries),
212*554f68d3SGreg Clayton     ENTRY_CHILDREN          ("line"                , Invalid                , None      , g_line_child_entries),
213*554f68d3SGreg Clayton     ENTRY_CHILDREN          ("module"              , Invalid                , None      , g_module_child_entries),
214*554f68d3SGreg Clayton     ENTRY_CHILDREN          ("process"             , Invalid                , None      , g_process_child_entries),
215*554f68d3SGreg Clayton     ENTRY_CHILDREN          ("script"              , Invalid                , None      , g_script_child_entries),
216*554f68d3SGreg Clayton     ENTRY_CHILDREN_KEEP_SEP ("svar"                , VariableSynthetic      , None      , g_svar_child_entries),
217*554f68d3SGreg Clayton     ENTRY_CHILDREN          ("thread"              , Invalid                , None      , g_thread_child_entries),
218*554f68d3SGreg Clayton     ENTRY_CHILDREN          ("target"              , Invalid                , None      , g_target_child_entries),
219*554f68d3SGreg Clayton     ENTRY_CHILDREN_KEEP_SEP ("var"                 , Variable               , None      , g_var_child_entries),
220*554f68d3SGreg Clayton };
221*554f68d3SGreg Clayton 
222*554f68d3SGreg Clayton static FormatEntity::Entry::Definition g_root = ENTRY_CHILDREN ("<root>", Root, None, g_top_level_entries);
223*554f68d3SGreg Clayton 
224*554f68d3SGreg Clayton 
225*554f68d3SGreg Clayton FormatEntity::Entry::Entry (llvm::StringRef s) :
226*554f68d3SGreg Clayton     string (s.data(), s.size()),
227*554f68d3SGreg Clayton     printf_format (),
228*554f68d3SGreg Clayton     children (),
229*554f68d3SGreg Clayton     definition (NULL),
230*554f68d3SGreg Clayton     type (Type::String),
231*554f68d3SGreg Clayton     fmt (lldb::eFormatDefault),
232*554f68d3SGreg Clayton     number (0),
233*554f68d3SGreg Clayton     deref (false)
234*554f68d3SGreg Clayton {
235*554f68d3SGreg Clayton }
236*554f68d3SGreg Clayton 
237*554f68d3SGreg Clayton FormatEntity::Entry::Entry (char ch) :
238*554f68d3SGreg Clayton     string (1, ch),
239*554f68d3SGreg Clayton     printf_format (),
240*554f68d3SGreg Clayton     children (),
241*554f68d3SGreg Clayton     definition (NULL),
242*554f68d3SGreg Clayton     type (Type::String),
243*554f68d3SGreg Clayton     fmt (lldb::eFormatDefault),
244*554f68d3SGreg Clayton     number (0),
245*554f68d3SGreg Clayton     deref (false)
246*554f68d3SGreg Clayton {
247*554f68d3SGreg Clayton }
248*554f68d3SGreg Clayton 
249*554f68d3SGreg Clayton void
250*554f68d3SGreg Clayton FormatEntity::Entry::AppendChar (char ch)
251*554f68d3SGreg Clayton {
252*554f68d3SGreg Clayton     if (children.empty() || children.back().type != Entry::Type::String)
253*554f68d3SGreg Clayton         children.push_back(Entry(ch));
254*554f68d3SGreg Clayton     else
255*554f68d3SGreg Clayton         children.back().string.append(1, ch);
256*554f68d3SGreg Clayton }
257*554f68d3SGreg Clayton 
258*554f68d3SGreg Clayton void
259*554f68d3SGreg Clayton FormatEntity::Entry::AppendText (const llvm::StringRef &s)
260*554f68d3SGreg Clayton {
261*554f68d3SGreg Clayton     if (children.empty() || children.back().type != Entry::Type::String)
262*554f68d3SGreg Clayton         children.push_back(Entry(s));
263*554f68d3SGreg Clayton     else
264*554f68d3SGreg Clayton         children.back().string.append(s.data(), s.size());
265*554f68d3SGreg Clayton }
266*554f68d3SGreg Clayton 
267*554f68d3SGreg Clayton void
268*554f68d3SGreg Clayton FormatEntity::Entry::AppendText (const char *cstr)
269*554f68d3SGreg Clayton {
270*554f68d3SGreg Clayton     return AppendText (llvm::StringRef(cstr));
271*554f68d3SGreg Clayton }
272*554f68d3SGreg Clayton 
273*554f68d3SGreg Clayton 
274*554f68d3SGreg Clayton Error
275*554f68d3SGreg Clayton FormatEntity::Parse (const llvm::StringRef &format_str, Entry &entry)
276*554f68d3SGreg Clayton {
277*554f68d3SGreg Clayton     entry.Clear();
278*554f68d3SGreg Clayton     entry.type = Entry::Type::Root;
279*554f68d3SGreg Clayton     llvm::StringRef modifiable_format (format_str);
280*554f68d3SGreg Clayton     return ParseInternal (modifiable_format, entry, 0);
281*554f68d3SGreg Clayton }
282*554f68d3SGreg Clayton 
283*554f68d3SGreg Clayton #define ENUM_TO_CSTR(eee) case FormatEntity::Entry::Type::eee: return #eee
284*554f68d3SGreg Clayton 
285*554f68d3SGreg Clayton const char *
286*554f68d3SGreg Clayton FormatEntity::Entry::TypeToCString (Type t)
287*554f68d3SGreg Clayton {
288*554f68d3SGreg Clayton     switch (t)
289*554f68d3SGreg Clayton     {
290*554f68d3SGreg Clayton     ENUM_TO_CSTR(Invalid);
291*554f68d3SGreg Clayton     ENUM_TO_CSTR(ParentNumber);
292*554f68d3SGreg Clayton     ENUM_TO_CSTR(ParentString);
293*554f68d3SGreg Clayton     ENUM_TO_CSTR(InsertString);
294*554f68d3SGreg Clayton     ENUM_TO_CSTR(Root);
295*554f68d3SGreg Clayton     ENUM_TO_CSTR(String);
296*554f68d3SGreg Clayton     ENUM_TO_CSTR(Scope);
297*554f68d3SGreg Clayton     ENUM_TO_CSTR(Variable);
298*554f68d3SGreg Clayton     ENUM_TO_CSTR(VariableSynthetic);
299*554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptVariable);
300*554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptVariableSynthetic);
301*554f68d3SGreg Clayton     ENUM_TO_CSTR(AddressLoad);
302*554f68d3SGreg Clayton     ENUM_TO_CSTR(AddressFile);
303*554f68d3SGreg Clayton     ENUM_TO_CSTR(AddressLoadOrFile);
304*554f68d3SGreg Clayton     ENUM_TO_CSTR(ProcessID);
305*554f68d3SGreg Clayton     ENUM_TO_CSTR(ProcessFile);
306*554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptProcess);
307*554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadID);
308*554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadProtocolID);
309*554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadIndexID);
310*554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadName);
311*554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadQueue);
312*554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadStopReason);
313*554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadReturnValue);
314*554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadCompletedExpression);
315*554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptThread);
316*554f68d3SGreg Clayton     ENUM_TO_CSTR(ThreadInfo);
317*554f68d3SGreg Clayton     ENUM_TO_CSTR(TargetArch);
318*554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptTarget);
319*554f68d3SGreg Clayton     ENUM_TO_CSTR(ModuleFile);
320*554f68d3SGreg Clayton     ENUM_TO_CSTR(File);
321*554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameIndex);
322*554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterPC);
323*554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterSP);
324*554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterFP);
325*554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterFlags);
326*554f68d3SGreg Clayton     ENUM_TO_CSTR(FrameRegisterByName);
327*554f68d3SGreg Clayton     ENUM_TO_CSTR(ScriptFrame);
328*554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionID);
329*554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionDidChange);
330*554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionInitialFunction);
331*554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionName);
332*554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionNameWithArgs);
333*554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionNameNoArgs);
334*554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionAddrOffset);
335*554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionAddrOffsetConcrete);
336*554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionLineOffset);
337*554f68d3SGreg Clayton     ENUM_TO_CSTR(FunctionPCOffset);
338*554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryFile);
339*554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryLineNumber);
340*554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryStartAddress);
341*554f68d3SGreg Clayton     ENUM_TO_CSTR(LineEntryEndAddress);
342*554f68d3SGreg Clayton     ENUM_TO_CSTR(CurrentPCArrow);
343*554f68d3SGreg Clayton     }
344*554f68d3SGreg Clayton     return "???";
345*554f68d3SGreg Clayton }
346*554f68d3SGreg Clayton 
347*554f68d3SGreg Clayton #undef ENUM_TO_CSTR
348*554f68d3SGreg Clayton 
349*554f68d3SGreg Clayton void
350*554f68d3SGreg Clayton FormatEntity::Entry::Dump (Stream &s, int depth) const
351*554f68d3SGreg Clayton {
352*554f68d3SGreg Clayton     s.Printf ("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type));
353*554f68d3SGreg Clayton     if (fmt != eFormatDefault)
354*554f68d3SGreg Clayton         s.Printf ("lldb-format = %s, ", FormatManager::GetFormatAsCString (fmt));
355*554f68d3SGreg Clayton     if (!string.empty())
356*554f68d3SGreg Clayton         s.Printf ("string = \"%s\"", string.c_str());
357*554f68d3SGreg Clayton     if (!printf_format.empty())
358*554f68d3SGreg Clayton         s.Printf ("printf_format = \"%s\"", printf_format.c_str());
359*554f68d3SGreg Clayton     if (number != 0)
360*554f68d3SGreg Clayton         s.Printf ("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number);
361*554f68d3SGreg Clayton     if (deref)
362*554f68d3SGreg Clayton         s.Printf ("deref = true, ");
363*554f68d3SGreg Clayton     s.EOL();
364*554f68d3SGreg Clayton     for (const auto &child : children)
365*554f68d3SGreg Clayton     {
366*554f68d3SGreg Clayton         child.Dump(s, depth + 1);
367*554f68d3SGreg Clayton     }
368*554f68d3SGreg Clayton }
369*554f68d3SGreg Clayton 
370*554f68d3SGreg Clayton 
371*554f68d3SGreg Clayton template <typename T>
372*554f68d3SGreg Clayton static bool RunScriptFormatKeyword(Stream &s,
373*554f68d3SGreg Clayton                                    const SymbolContext *sc,
374*554f68d3SGreg Clayton                                    const ExecutionContext *exe_ctx,
375*554f68d3SGreg Clayton                                    T t,
376*554f68d3SGreg Clayton                                    const char *script_function_name)
377*554f68d3SGreg Clayton {
378*554f68d3SGreg Clayton     Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
379*554f68d3SGreg Clayton 
380*554f68d3SGreg Clayton     if (target)
381*554f68d3SGreg Clayton     {
382*554f68d3SGreg Clayton         ScriptInterpreter *script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
383*554f68d3SGreg Clayton         if (script_interpreter)
384*554f68d3SGreg Clayton         {
385*554f68d3SGreg Clayton             Error error;
386*554f68d3SGreg Clayton             std::string script_output;
387*554f68d3SGreg Clayton 
388*554f68d3SGreg Clayton             if (script_interpreter->RunScriptFormatKeyword(script_function_name, t, script_output, error) && error.Success())
389*554f68d3SGreg Clayton             {
390*554f68d3SGreg Clayton                 s.Printf("%s", script_output.c_str());
391*554f68d3SGreg Clayton                 return true;
392*554f68d3SGreg Clayton             }
393*554f68d3SGreg Clayton             else
394*554f68d3SGreg Clayton             {
395*554f68d3SGreg Clayton                 s.Printf("<error: %s>",error.AsCString());
396*554f68d3SGreg Clayton             }
397*554f68d3SGreg Clayton         }
398*554f68d3SGreg Clayton     }
399*554f68d3SGreg Clayton     return false;
400*554f68d3SGreg Clayton }
401*554f68d3SGreg Clayton 
402*554f68d3SGreg Clayton static bool
403*554f68d3SGreg Clayton DumpAddress (Stream &s,
404*554f68d3SGreg Clayton              const SymbolContext *sc,
405*554f68d3SGreg Clayton              const ExecutionContext *exe_ctx,
406*554f68d3SGreg Clayton              const Address &addr,
407*554f68d3SGreg Clayton              bool print_file_addr_or_load_addr)
408*554f68d3SGreg Clayton {
409*554f68d3SGreg Clayton     Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
410*554f68d3SGreg Clayton     addr_t vaddr = LLDB_INVALID_ADDRESS;
411*554f68d3SGreg Clayton     if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
412*554f68d3SGreg Clayton         vaddr = addr.GetLoadAddress (target);
413*554f68d3SGreg Clayton     if (vaddr == LLDB_INVALID_ADDRESS)
414*554f68d3SGreg Clayton         vaddr = addr.GetFileAddress ();
415*554f68d3SGreg Clayton 
416*554f68d3SGreg Clayton     if (vaddr != LLDB_INVALID_ADDRESS)
417*554f68d3SGreg Clayton     {
418*554f68d3SGreg Clayton         int addr_width = 0;
419*554f68d3SGreg Clayton         if (exe_ctx && target)
420*554f68d3SGreg Clayton         {
421*554f68d3SGreg Clayton             addr_width = target->GetArchitecture().GetAddressByteSize() * 2;
422*554f68d3SGreg Clayton         }
423*554f68d3SGreg Clayton         if (addr_width == 0)
424*554f68d3SGreg Clayton             addr_width = 16;
425*554f68d3SGreg Clayton         if (print_file_addr_or_load_addr)
426*554f68d3SGreg Clayton         {
427*554f68d3SGreg Clayton             ExecutionContextScope *exe_scope = NULL;
428*554f68d3SGreg Clayton             if (exe_ctx)
429*554f68d3SGreg Clayton                 exe_scope = exe_ctx->GetBestExecutionContextScope();
430*554f68d3SGreg Clayton             addr.Dump (&s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0);
431*554f68d3SGreg Clayton         }
432*554f68d3SGreg Clayton         else
433*554f68d3SGreg Clayton         {
434*554f68d3SGreg Clayton             s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr);
435*554f68d3SGreg Clayton         }
436*554f68d3SGreg Clayton         return true;
437*554f68d3SGreg Clayton     }
438*554f68d3SGreg Clayton     return false;
439*554f68d3SGreg Clayton }
440*554f68d3SGreg Clayton 
441*554f68d3SGreg Clayton static bool
442*554f68d3SGreg Clayton DumpAddressOffsetFromFunction (Stream &s,
443*554f68d3SGreg Clayton                                const SymbolContext *sc,
444*554f68d3SGreg Clayton                                const ExecutionContext *exe_ctx,
445*554f68d3SGreg Clayton                                const Address &format_addr,
446*554f68d3SGreg Clayton                                bool concrete_only,
447*554f68d3SGreg Clayton                                bool no_padding)
448*554f68d3SGreg Clayton {
449*554f68d3SGreg Clayton     if (format_addr.IsValid())
450*554f68d3SGreg Clayton     {
451*554f68d3SGreg Clayton         Address func_addr;
452*554f68d3SGreg Clayton 
453*554f68d3SGreg Clayton         if (sc)
454*554f68d3SGreg Clayton         {
455*554f68d3SGreg Clayton             if (sc->function)
456*554f68d3SGreg Clayton             {
457*554f68d3SGreg Clayton                 func_addr = sc->function->GetAddressRange().GetBaseAddress();
458*554f68d3SGreg Clayton                 if (sc->block && !concrete_only)
459*554f68d3SGreg Clayton                 {
460*554f68d3SGreg Clayton                     // Check to make sure we aren't in an inline
461*554f68d3SGreg Clayton                     // function. If we are, use the inline block
462*554f68d3SGreg Clayton                     // range that contains "format_addr" since
463*554f68d3SGreg Clayton                     // blocks can be discontiguous.
464*554f68d3SGreg Clayton                     Block *inline_block = sc->block->GetContainingInlinedBlock ();
465*554f68d3SGreg Clayton                     AddressRange inline_range;
466*554f68d3SGreg Clayton                     if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range))
467*554f68d3SGreg Clayton                         func_addr = inline_range.GetBaseAddress();
468*554f68d3SGreg Clayton                 }
469*554f68d3SGreg Clayton             }
470*554f68d3SGreg Clayton             else if (sc->symbol && sc->symbol->ValueIsAddress())
471*554f68d3SGreg Clayton                 func_addr = sc->symbol->GetAddress();
472*554f68d3SGreg Clayton         }
473*554f68d3SGreg Clayton 
474*554f68d3SGreg Clayton         if (func_addr.IsValid())
475*554f68d3SGreg Clayton         {
476*554f68d3SGreg Clayton             const char *addr_offset_padding = no_padding ? "" : " ";
477*554f68d3SGreg Clayton 
478*554f68d3SGreg Clayton             if (func_addr.GetSection() == format_addr.GetSection())
479*554f68d3SGreg Clayton             {
480*554f68d3SGreg Clayton                 addr_t func_file_addr = func_addr.GetFileAddress();
481*554f68d3SGreg Clayton                 addr_t addr_file_addr = format_addr.GetFileAddress();
482*554f68d3SGreg Clayton                 if (addr_file_addr > func_file_addr)
483*554f68d3SGreg Clayton                     s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_file_addr - func_file_addr);
484*554f68d3SGreg Clayton                 else if (addr_file_addr < func_file_addr)
485*554f68d3SGreg Clayton                     s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_file_addr - addr_file_addr);
486*554f68d3SGreg Clayton                 return true;
487*554f68d3SGreg Clayton             }
488*554f68d3SGreg Clayton             else
489*554f68d3SGreg Clayton             {
490*554f68d3SGreg Clayton                 Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
491*554f68d3SGreg Clayton                 if (target)
492*554f68d3SGreg Clayton                 {
493*554f68d3SGreg Clayton                     addr_t func_load_addr = func_addr.GetLoadAddress (target);
494*554f68d3SGreg Clayton                     addr_t addr_load_addr = format_addr.GetLoadAddress (target);
495*554f68d3SGreg Clayton                     if (addr_load_addr > func_load_addr)
496*554f68d3SGreg Clayton                         s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_load_addr - func_load_addr);
497*554f68d3SGreg Clayton                     else if (addr_load_addr < func_load_addr)
498*554f68d3SGreg Clayton                         s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_load_addr - addr_load_addr);
499*554f68d3SGreg Clayton                     return true;
500*554f68d3SGreg Clayton                 }
501*554f68d3SGreg Clayton             }
502*554f68d3SGreg Clayton         }
503*554f68d3SGreg Clayton     }
504*554f68d3SGreg Clayton     return false;
505*554f68d3SGreg Clayton }
506*554f68d3SGreg Clayton 
507*554f68d3SGreg Clayton static bool
508*554f68d3SGreg Clayton ScanBracketedRange (llvm::StringRef subpath,
509*554f68d3SGreg Clayton                     size_t& close_bracket_index,
510*554f68d3SGreg Clayton                     const char*& var_name_final_if_array_range,
511*554f68d3SGreg Clayton                     int64_t& index_lower,
512*554f68d3SGreg Clayton                     int64_t& index_higher)
513*554f68d3SGreg Clayton {
514*554f68d3SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
515*554f68d3SGreg Clayton     close_bracket_index = llvm::StringRef::npos;
516*554f68d3SGreg Clayton     const size_t open_bracket_index = subpath.find('[');
517*554f68d3SGreg Clayton     if (open_bracket_index == llvm::StringRef::npos)
518*554f68d3SGreg Clayton     {
519*554f68d3SGreg Clayton         if (log)
520*554f68d3SGreg Clayton             log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
521*554f68d3SGreg Clayton         return false;
522*554f68d3SGreg Clayton     }
523*554f68d3SGreg Clayton 
524*554f68d3SGreg Clayton     close_bracket_index = subpath.find(']', open_bracket_index + 1);
525*554f68d3SGreg Clayton 
526*554f68d3SGreg Clayton     if (close_bracket_index == llvm::StringRef::npos)
527*554f68d3SGreg Clayton     {
528*554f68d3SGreg Clayton         if (log)
529*554f68d3SGreg Clayton             log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely");
530*554f68d3SGreg Clayton         return false;
531*554f68d3SGreg Clayton     }
532*554f68d3SGreg Clayton     else
533*554f68d3SGreg Clayton     {
534*554f68d3SGreg Clayton         var_name_final_if_array_range = subpath.data() + open_bracket_index;
535*554f68d3SGreg Clayton 
536*554f68d3SGreg Clayton         if (close_bracket_index - open_bracket_index == 1)
537*554f68d3SGreg Clayton         {
538*554f68d3SGreg Clayton             if (log)
539*554f68d3SGreg Clayton                 log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data");
540*554f68d3SGreg Clayton             index_lower = 0;
541*554f68d3SGreg Clayton         }
542*554f68d3SGreg Clayton         else
543*554f68d3SGreg Clayton         {
544*554f68d3SGreg Clayton             const size_t separator_index = subpath.find('-', open_bracket_index + 1);
545*554f68d3SGreg Clayton 
546*554f68d3SGreg Clayton             if (separator_index == llvm::StringRef::npos)
547*554f68d3SGreg Clayton             {
548*554f68d3SGreg Clayton                 const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
549*554f68d3SGreg Clayton                 index_lower = ::strtoul (index_lower_cstr, NULL, 0);
550*554f68d3SGreg Clayton                 index_higher = index_lower;
551*554f68d3SGreg Clayton                 if (log)
552*554f68d3SGreg Clayton                     log->Printf("[ScanBracketedRange] [%" PRId64 "] detected, high index is same", index_lower);
553*554f68d3SGreg Clayton             }
554*554f68d3SGreg Clayton             else
555*554f68d3SGreg Clayton             {
556*554f68d3SGreg Clayton                 const char *index_lower_cstr = subpath.data() + open_bracket_index + 1;
557*554f68d3SGreg Clayton                 const char *index_higher_cstr = subpath.data() + separator_index + 1;
558*554f68d3SGreg Clayton                 index_lower = ::strtoul (index_lower_cstr, NULL, 0);
559*554f68d3SGreg Clayton                 index_higher = ::strtoul (index_higher_cstr, NULL, 0);
560*554f68d3SGreg Clayton                 if (log)
561*554f68d3SGreg Clayton                     log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", index_lower, index_higher);
562*554f68d3SGreg Clayton             }
563*554f68d3SGreg Clayton             if (index_lower > index_higher && index_higher > 0)
564*554f68d3SGreg Clayton             {
565*554f68d3SGreg Clayton                 if (log)
566*554f68d3SGreg Clayton                     log->Printf("[ScanBracketedRange] swapping indices");
567*554f68d3SGreg Clayton                 const int64_t temp = index_lower;
568*554f68d3SGreg Clayton                 index_lower = index_higher;
569*554f68d3SGreg Clayton                 index_higher = temp;
570*554f68d3SGreg Clayton             }
571*554f68d3SGreg Clayton         }
572*554f68d3SGreg Clayton     }
573*554f68d3SGreg Clayton     return true;
574*554f68d3SGreg Clayton }
575*554f68d3SGreg Clayton 
576*554f68d3SGreg Clayton static bool
577*554f68d3SGreg Clayton DumpFile (Stream &s, const FileSpec &file, FileKind file_kind)
578*554f68d3SGreg Clayton {
579*554f68d3SGreg Clayton     switch (file_kind)
580*554f68d3SGreg Clayton     {
581*554f68d3SGreg Clayton     case FileKind::FileError:
582*554f68d3SGreg Clayton         break;
583*554f68d3SGreg Clayton 
584*554f68d3SGreg Clayton     case FileKind::Basename:
585*554f68d3SGreg Clayton         if (file.GetFilename())
586*554f68d3SGreg Clayton         {
587*554f68d3SGreg Clayton             s << file.GetFilename();
588*554f68d3SGreg Clayton             return true;
589*554f68d3SGreg Clayton         }
590*554f68d3SGreg Clayton         break;
591*554f68d3SGreg Clayton 
592*554f68d3SGreg Clayton     case FileKind::Dirname:
593*554f68d3SGreg Clayton         if (file.GetDirectory())
594*554f68d3SGreg Clayton         {
595*554f68d3SGreg Clayton             s << file.GetDirectory();
596*554f68d3SGreg Clayton             return true;
597*554f68d3SGreg Clayton         }
598*554f68d3SGreg Clayton         break;
599*554f68d3SGreg Clayton 
600*554f68d3SGreg Clayton     case FileKind::Fullpath:
601*554f68d3SGreg Clayton         if (file)
602*554f68d3SGreg Clayton         {
603*554f68d3SGreg Clayton             s << file;
604*554f68d3SGreg Clayton             return true;
605*554f68d3SGreg Clayton         }
606*554f68d3SGreg Clayton         break;
607*554f68d3SGreg Clayton     }
608*554f68d3SGreg Clayton     return false;
609*554f68d3SGreg Clayton }
610*554f68d3SGreg Clayton 
611*554f68d3SGreg Clayton static bool
612*554f68d3SGreg Clayton DumpRegister (Stream &s,
613*554f68d3SGreg Clayton               StackFrame *frame,
614*554f68d3SGreg Clayton               RegisterKind reg_kind,
615*554f68d3SGreg Clayton               uint32_t reg_num,
616*554f68d3SGreg Clayton               Format format)
617*554f68d3SGreg Clayton 
618*554f68d3SGreg Clayton {
619*554f68d3SGreg Clayton     if (frame)
620*554f68d3SGreg Clayton     {
621*554f68d3SGreg Clayton         RegisterContext *reg_ctx = frame->GetRegisterContext().get();
622*554f68d3SGreg Clayton 
623*554f68d3SGreg Clayton         if (reg_ctx)
624*554f68d3SGreg Clayton         {
625*554f68d3SGreg Clayton             const uint32_t lldb_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
626*554f68d3SGreg Clayton             if (lldb_reg_num != LLDB_INVALID_REGNUM)
627*554f68d3SGreg Clayton             {
628*554f68d3SGreg Clayton                 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (lldb_reg_num);
629*554f68d3SGreg Clayton                 if (reg_info)
630*554f68d3SGreg Clayton                 {
631*554f68d3SGreg Clayton                     RegisterValue reg_value;
632*554f68d3SGreg Clayton                     if (reg_ctx->ReadRegister (reg_info, reg_value))
633*554f68d3SGreg Clayton                     {
634*554f68d3SGreg Clayton                         reg_value.Dump(&s, reg_info, false, false, format);
635*554f68d3SGreg Clayton                         return true;
636*554f68d3SGreg Clayton                     }
637*554f68d3SGreg Clayton                 }
638*554f68d3SGreg Clayton             }
639*554f68d3SGreg Clayton         }
640*554f68d3SGreg Clayton     }
641*554f68d3SGreg Clayton     return false;
642*554f68d3SGreg Clayton }
643*554f68d3SGreg Clayton 
644*554f68d3SGreg Clayton 
645*554f68d3SGreg Clayton static ValueObjectSP
646*554f68d3SGreg Clayton ExpandIndexedExpression (ValueObject* valobj,
647*554f68d3SGreg Clayton                          size_t index,
648*554f68d3SGreg Clayton                          StackFrame* frame,
649*554f68d3SGreg Clayton                          bool deref_pointer)
650*554f68d3SGreg Clayton {
651*554f68d3SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
652*554f68d3SGreg Clayton     const char* ptr_deref_format = "[%d]";
653*554f68d3SGreg Clayton     std::string ptr_deref_buffer(10,0);
654*554f68d3SGreg Clayton     ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index);
655*554f68d3SGreg Clayton     if (log)
656*554f68d3SGreg Clayton         log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.c_str());
657*554f68d3SGreg Clayton     const char* first_unparsed;
658*554f68d3SGreg Clayton     ValueObject::GetValueForExpressionPathOptions options;
659*554f68d3SGreg Clayton     ValueObject::ExpressionPathEndResultType final_value_type;
660*554f68d3SGreg Clayton     ValueObject::ExpressionPathScanEndReason reason_to_stop;
661*554f68d3SGreg Clayton     ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing);
662*554f68d3SGreg Clayton     ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.c_str(),
663*554f68d3SGreg Clayton                                                             &first_unparsed,
664*554f68d3SGreg Clayton                                                             &reason_to_stop,
665*554f68d3SGreg Clayton                                                             &final_value_type,
666*554f68d3SGreg Clayton                                                             options,
667*554f68d3SGreg Clayton                                                             &what_next);
668*554f68d3SGreg Clayton     if (!item)
669*554f68d3SGreg Clayton     {
670*554f68d3SGreg Clayton         if (log)
671*554f68d3SGreg Clayton             log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d,"
672*554f68d3SGreg Clayton                         " final_value_type %d",
673*554f68d3SGreg Clayton                         first_unparsed, reason_to_stop, final_value_type);
674*554f68d3SGreg Clayton     }
675*554f68d3SGreg Clayton     else
676*554f68d3SGreg Clayton     {
677*554f68d3SGreg Clayton         if (log)
678*554f68d3SGreg Clayton             log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d,"
679*554f68d3SGreg Clayton                         " final_value_type %d",
680*554f68d3SGreg Clayton                         first_unparsed, reason_to_stop, final_value_type);
681*554f68d3SGreg Clayton     }
682*554f68d3SGreg Clayton     return item;
683*554f68d3SGreg Clayton }
684*554f68d3SGreg Clayton 
685*554f68d3SGreg Clayton static char
686*554f68d3SGreg Clayton ConvertValueObjectStyleToChar(ValueObject::ValueObjectRepresentationStyle style)
687*554f68d3SGreg Clayton {
688*554f68d3SGreg Clayton     switch (style)
689*554f68d3SGreg Clayton     {
690*554f68d3SGreg Clayton         case ValueObject::eValueObjectRepresentationStyleLanguageSpecific:  return '@';
691*554f68d3SGreg Clayton         case ValueObject::eValueObjectRepresentationStyleValue:             return 'V';
692*554f68d3SGreg Clayton         case ValueObject::eValueObjectRepresentationStyleLocation:          return 'L';
693*554f68d3SGreg Clayton         case ValueObject::eValueObjectRepresentationStyleSummary:           return 'S';
694*554f68d3SGreg Clayton         case ValueObject::eValueObjectRepresentationStyleChildrenCount:     return '#';
695*554f68d3SGreg Clayton         case ValueObject::eValueObjectRepresentationStyleType:              return 'T';
696*554f68d3SGreg Clayton         case ValueObject::eValueObjectRepresentationStyleName:              return 'N';
697*554f68d3SGreg Clayton         case ValueObject::eValueObjectRepresentationStyleExpressionPath:    return '>';
698*554f68d3SGreg Clayton     }
699*554f68d3SGreg Clayton     return '\0';
700*554f68d3SGreg Clayton }
701*554f68d3SGreg Clayton 
702*554f68d3SGreg Clayton static bool
703*554f68d3SGreg Clayton DumpValue (Stream &s,
704*554f68d3SGreg Clayton            const SymbolContext *sc,
705*554f68d3SGreg Clayton            const ExecutionContext *exe_ctx,
706*554f68d3SGreg Clayton            const FormatEntity::Entry &entry,
707*554f68d3SGreg Clayton            ValueObject *valobj)
708*554f68d3SGreg Clayton {
709*554f68d3SGreg Clayton     if (valobj == NULL)
710*554f68d3SGreg Clayton         return false;
711*554f68d3SGreg Clayton 
712*554f68d3SGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
713*554f68d3SGreg Clayton     Format custom_format = eFormatInvalid;
714*554f68d3SGreg Clayton     ValueObject::ValueObjectRepresentationStyle val_obj_display = entry.string.empty() ? ValueObject::eValueObjectRepresentationStyleValue : ValueObject::eValueObjectRepresentationStyleSummary;
715*554f68d3SGreg Clayton 
716*554f68d3SGreg Clayton     bool do_deref_pointer = entry.deref;
717*554f68d3SGreg Clayton     bool is_script = false;
718*554f68d3SGreg Clayton     switch (entry.type)
719*554f68d3SGreg Clayton     {
720*554f68d3SGreg Clayton         case FormatEntity::Entry::Type::ScriptVariable:
721*554f68d3SGreg Clayton             is_script = true;
722*554f68d3SGreg Clayton             break;
723*554f68d3SGreg Clayton 
724*554f68d3SGreg Clayton         case FormatEntity::Entry::Type::Variable:
725*554f68d3SGreg Clayton             custom_format = entry.fmt;
726*554f68d3SGreg Clayton             val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
727*554f68d3SGreg Clayton             break;
728*554f68d3SGreg Clayton 
729*554f68d3SGreg Clayton         case FormatEntity::Entry::Type::ScriptVariableSynthetic:
730*554f68d3SGreg Clayton             is_script = true;
731*554f68d3SGreg Clayton             // Fall through
732*554f68d3SGreg Clayton         case FormatEntity::Entry::Type::VariableSynthetic:
733*554f68d3SGreg Clayton             custom_format = entry.fmt;
734*554f68d3SGreg Clayton             val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number;
735*554f68d3SGreg Clayton             if (!valobj->IsSynthetic())
736*554f68d3SGreg Clayton             {
737*554f68d3SGreg Clayton                 valobj = valobj->GetSyntheticValue().get();
738*554f68d3SGreg Clayton                 if (valobj == nullptr)
739*554f68d3SGreg Clayton                     return false;
740*554f68d3SGreg Clayton             }
741*554f68d3SGreg Clayton             break;
742*554f68d3SGreg Clayton 
743*554f68d3SGreg Clayton         default:
744*554f68d3SGreg Clayton             return false;
745*554f68d3SGreg Clayton     }
746*554f68d3SGreg Clayton 
747*554f68d3SGreg Clayton     if (valobj == NULL)
748*554f68d3SGreg Clayton         return false;
749*554f68d3SGreg Clayton 
750*554f68d3SGreg Clayton     ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ?
751*554f68d3SGreg Clayton                                                       ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing);
752*554f68d3SGreg Clayton     ValueObject::GetValueForExpressionPathOptions options;
753*554f68d3SGreg Clayton     options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren();
754*554f68d3SGreg Clayton     ValueObject* target = NULL;
755*554f68d3SGreg Clayton     const char* var_name_final_if_array_range = NULL;
756*554f68d3SGreg Clayton     size_t close_bracket_index = llvm::StringRef::npos;
757*554f68d3SGreg Clayton     int64_t index_lower = -1;
758*554f68d3SGreg Clayton     int64_t index_higher = -1;
759*554f68d3SGreg Clayton     bool is_array_range = false;
760*554f68d3SGreg Clayton     const char* first_unparsed;
761*554f68d3SGreg Clayton     bool was_plain_var = false;
762*554f68d3SGreg Clayton     bool was_var_format = false;
763*554f68d3SGreg Clayton     bool was_var_indexed = false;
764*554f68d3SGreg Clayton     ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
765*554f68d3SGreg Clayton     ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain;
766*554f68d3SGreg Clayton 
767*554f68d3SGreg Clayton     if (is_script)
768*554f68d3SGreg Clayton     {
769*554f68d3SGreg Clayton         return RunScriptFormatKeyword (s, sc, exe_ctx, valobj, entry.string.c_str());
770*554f68d3SGreg Clayton     }
771*554f68d3SGreg Clayton 
772*554f68d3SGreg Clayton     llvm::StringRef subpath (entry.string);
773*554f68d3SGreg Clayton     // simplest case ${var}, just print valobj's value
774*554f68d3SGreg Clayton     if (entry.string.empty())
775*554f68d3SGreg Clayton     {
776*554f68d3SGreg Clayton         if (entry.printf_format.empty() && entry.fmt == eFormatDefault && entry.number == ValueObject::eValueObjectRepresentationStyleValue)
777*554f68d3SGreg Clayton             was_plain_var = true;
778*554f68d3SGreg Clayton         else
779*554f68d3SGreg Clayton             was_var_format = true;
780*554f68d3SGreg Clayton         target = valobj;
781*554f68d3SGreg Clayton     }
782*554f68d3SGreg Clayton     else    // this is ${var.something} or multiple .something nested
783*554f68d3SGreg Clayton     {
784*554f68d3SGreg Clayton         if (entry.string[0] == '[')
785*554f68d3SGreg Clayton             was_var_indexed = true;
786*554f68d3SGreg Clayton         ScanBracketedRange (subpath,
787*554f68d3SGreg Clayton                             close_bracket_index,
788*554f68d3SGreg Clayton                             var_name_final_if_array_range,
789*554f68d3SGreg Clayton                             index_lower,
790*554f68d3SGreg Clayton                             index_higher);
791*554f68d3SGreg Clayton 
792*554f68d3SGreg Clayton         Error error;
793*554f68d3SGreg Clayton 
794*554f68d3SGreg Clayton         const std::string &expr_path = entry.string;
795*554f68d3SGreg Clayton 
796*554f68d3SGreg Clayton         if (log)
797*554f68d3SGreg Clayton             log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.c_str());
798*554f68d3SGreg Clayton 
799*554f68d3SGreg Clayton         target = valobj->GetValueForExpressionPath(expr_path.c_str(),
800*554f68d3SGreg Clayton                                                    &first_unparsed,
801*554f68d3SGreg Clayton                                                    &reason_to_stop,
802*554f68d3SGreg Clayton                                                    &final_value_type,
803*554f68d3SGreg Clayton                                                    options,
804*554f68d3SGreg Clayton                                                    &what_next).get();
805*554f68d3SGreg Clayton 
806*554f68d3SGreg Clayton         if (!target)
807*554f68d3SGreg Clayton         {
808*554f68d3SGreg Clayton             if (log)
809*554f68d3SGreg Clayton                 log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d,"
810*554f68d3SGreg Clayton                             " final_value_type %d",
811*554f68d3SGreg Clayton                             first_unparsed, reason_to_stop, final_value_type);
812*554f68d3SGreg Clayton             return false;
813*554f68d3SGreg Clayton         }
814*554f68d3SGreg Clayton         else
815*554f68d3SGreg Clayton         {
816*554f68d3SGreg Clayton             if (log)
817*554f68d3SGreg Clayton                 log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d,"
818*554f68d3SGreg Clayton                             " final_value_type %d",
819*554f68d3SGreg Clayton                             first_unparsed, reason_to_stop, final_value_type);
820*554f68d3SGreg Clayton             target = target->GetQualifiedRepresentationIfAvailable(target->GetDynamicValueType(), true).get();
821*554f68d3SGreg Clayton         }
822*554f68d3SGreg Clayton     }
823*554f68d3SGreg Clayton 
824*554f68d3SGreg Clayton 
825*554f68d3SGreg Clayton     is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange ||
826*554f68d3SGreg Clayton                       final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange);
827*554f68d3SGreg Clayton 
828*554f68d3SGreg Clayton     do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference);
829*554f68d3SGreg Clayton 
830*554f68d3SGreg Clayton     if (do_deref_pointer && !is_array_range)
831*554f68d3SGreg Clayton     {
832*554f68d3SGreg Clayton         // I have not deref-ed yet, let's do it
833*554f68d3SGreg Clayton         // this happens when we are not going through GetValueForVariableExpressionPath
834*554f68d3SGreg Clayton         // to get to the target ValueObject
835*554f68d3SGreg Clayton         Error error;
836*554f68d3SGreg Clayton         target = target->Dereference(error).get();
837*554f68d3SGreg Clayton         if (error.Fail())
838*554f68d3SGreg Clayton         {
839*554f68d3SGreg Clayton             if (log)
840*554f68d3SGreg Clayton                 log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \
841*554f68d3SGreg Clayton             return false;
842*554f68d3SGreg Clayton         }
843*554f68d3SGreg Clayton         do_deref_pointer = false;
844*554f68d3SGreg Clayton     }
845*554f68d3SGreg Clayton 
846*554f68d3SGreg Clayton     if (!target)
847*554f68d3SGreg Clayton     {
848*554f68d3SGreg Clayton         if (log)
849*554f68d3SGreg Clayton             log->Printf("[Debugger::FormatPrompt] could not calculate target for prompt expression");
850*554f68d3SGreg Clayton         return false;
851*554f68d3SGreg Clayton     }
852*554f68d3SGreg Clayton 
853*554f68d3SGreg Clayton     // we do not want to use the summary for a bitfield of type T:n
854*554f68d3SGreg Clayton     // if we were originally dealing with just a T - that would get
855*554f68d3SGreg Clayton     // us into an endless recursion
856*554f68d3SGreg Clayton     if (target->IsBitfield() && was_var_indexed)
857*554f68d3SGreg Clayton     {
858*554f68d3SGreg Clayton         // TODO: check for a (T:n)-specific summary - we should still obey that
859*554f68d3SGreg Clayton         StreamString bitfield_name;
860*554f68d3SGreg Clayton         bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize());
861*554f68d3SGreg Clayton         lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false));
862*554f68d3SGreg Clayton         if (val_obj_display == ValueObject::eValueObjectRepresentationStyleSummary && !DataVisualization::GetSummaryForType(type_sp))
863*554f68d3SGreg Clayton             val_obj_display = ValueObject::eValueObjectRepresentationStyleValue;
864*554f68d3SGreg Clayton     }
865*554f68d3SGreg Clayton 
866*554f68d3SGreg Clayton     // TODO use flags for these
867*554f68d3SGreg Clayton     const uint32_t type_info_flags = target->GetClangType().GetTypeInfo(NULL);
868*554f68d3SGreg Clayton     bool is_array = (type_info_flags & eTypeIsArray) != 0;
869*554f68d3SGreg Clayton     bool is_pointer = (type_info_flags & eTypeIsPointer) != 0;
870*554f68d3SGreg Clayton     bool is_aggregate = target->GetClangType().IsAggregateType();
871*554f68d3SGreg Clayton 
872*554f68d3SGreg Clayton     if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions
873*554f68d3SGreg Clayton     {
874*554f68d3SGreg Clayton         StreamString str_temp;
875*554f68d3SGreg Clayton         if (log)
876*554f68d3SGreg Clayton             log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range");
877*554f68d3SGreg Clayton 
878*554f68d3SGreg Clayton         if (target->HasSpecialPrintableRepresentation(val_obj_display, custom_format))
879*554f68d3SGreg Clayton         {
880*554f68d3SGreg Clayton             // try to use the special cases
881*554f68d3SGreg Clayton             bool success = target->DumpPrintableRepresentation(str_temp,
882*554f68d3SGreg Clayton                                                                val_obj_display,
883*554f68d3SGreg Clayton                                                                custom_format);
884*554f68d3SGreg Clayton             if (log)
885*554f68d3SGreg Clayton                 log->Printf("[Debugger::FormatPrompt] special cases did%s match", success ? "" : "n't");
886*554f68d3SGreg Clayton 
887*554f68d3SGreg Clayton             // should not happen
888*554f68d3SGreg Clayton             if (success)
889*554f68d3SGreg Clayton                 s << str_temp.GetData();
890*554f68d3SGreg Clayton             return true;
891*554f68d3SGreg Clayton         }
892*554f68d3SGreg Clayton         else
893*554f68d3SGreg Clayton         {
894*554f68d3SGreg Clayton             if (was_plain_var) // if ${var}
895*554f68d3SGreg Clayton             {
896*554f68d3SGreg Clayton                 s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
897*554f68d3SGreg Clayton             }
898*554f68d3SGreg Clayton             else if (is_pointer) // if pointer, value is the address stored
899*554f68d3SGreg Clayton             {
900*554f68d3SGreg Clayton                 target->DumpPrintableRepresentation (s,
901*554f68d3SGreg Clayton                                                      val_obj_display,
902*554f68d3SGreg Clayton                                                      custom_format,
903*554f68d3SGreg Clayton                                                      ValueObject::ePrintableRepresentationSpecialCasesDisable);
904*554f68d3SGreg Clayton             }
905*554f68d3SGreg Clayton             return true;
906*554f68d3SGreg Clayton         }
907*554f68d3SGreg Clayton     }
908*554f68d3SGreg Clayton 
909*554f68d3SGreg Clayton     // if directly trying to print ${var}, and this is an aggregate, display a nice
910*554f68d3SGreg Clayton     // type @ location message
911*554f68d3SGreg Clayton     if (is_aggregate && was_plain_var)
912*554f68d3SGreg Clayton     {
913*554f68d3SGreg Clayton         s << target->GetTypeName() << " @ " << target->GetLocationAsCString();
914*554f68d3SGreg Clayton         return true;
915*554f68d3SGreg Clayton     }
916*554f68d3SGreg Clayton 
917*554f68d3SGreg Clayton     // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it
918*554f68d3SGreg Clayton     if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue)))
919*554f68d3SGreg Clayton     {
920*554f68d3SGreg Clayton         s << "<invalid use of aggregate type>";
921*554f68d3SGreg Clayton         return true;
922*554f68d3SGreg Clayton     }
923*554f68d3SGreg Clayton 
924*554f68d3SGreg Clayton     if (!is_array_range)
925*554f68d3SGreg Clayton     {
926*554f68d3SGreg Clayton         if (log)
927*554f68d3SGreg Clayton             log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output");
928*554f68d3SGreg Clayton         return target->DumpPrintableRepresentation(s,val_obj_display, custom_format);
929*554f68d3SGreg Clayton     }
930*554f68d3SGreg Clayton     else
931*554f68d3SGreg Clayton     {
932*554f68d3SGreg Clayton         if (log)
933*554f68d3SGreg Clayton             log->Printf("[Debugger::FormatPrompt] checking if I can handle as array");
934*554f68d3SGreg Clayton         if (!is_array && !is_pointer)
935*554f68d3SGreg Clayton             return false;
936*554f68d3SGreg Clayton         if (log)
937*554f68d3SGreg Clayton             log->Printf("[Debugger::FormatPrompt] handle as array");
938*554f68d3SGreg Clayton         llvm::StringRef special_directions;
939*554f68d3SGreg Clayton         if (close_bracket_index != llvm::StringRef::npos && subpath.size() > close_bracket_index)
940*554f68d3SGreg Clayton         {
941*554f68d3SGreg Clayton             ConstString additional_data (subpath.drop_front(close_bracket_index+1));
942*554f68d3SGreg Clayton             StreamString special_directions_stream;
943*554f68d3SGreg Clayton             special_directions_stream.Printf("${%svar%s",
944*554f68d3SGreg Clayton                                              do_deref_pointer ? "*" : "",
945*554f68d3SGreg Clayton                                              additional_data.GetCString());
946*554f68d3SGreg Clayton 
947*554f68d3SGreg Clayton             if (entry.fmt != eFormatDefault)
948*554f68d3SGreg Clayton             {
949*554f68d3SGreg Clayton                 const char format_char = FormatManager::GetFormatAsFormatChar(entry.fmt);
950*554f68d3SGreg Clayton                 if (format_char != '\0')
951*554f68d3SGreg Clayton                     special_directions_stream.Printf("%%%c", format_char);
952*554f68d3SGreg Clayton                 else
953*554f68d3SGreg Clayton                 {
954*554f68d3SGreg Clayton                     const char *format_cstr = FormatManager::GetFormatAsCString(entry.fmt);
955*554f68d3SGreg Clayton                     special_directions_stream.Printf("%%%s", format_cstr);
956*554f68d3SGreg Clayton                 }
957*554f68d3SGreg Clayton             }
958*554f68d3SGreg Clayton             else if (entry.number != 0)
959*554f68d3SGreg Clayton             {
960*554f68d3SGreg Clayton                 const char style_char = ConvertValueObjectStyleToChar ((ValueObject::ValueObjectRepresentationStyle)entry.number);
961*554f68d3SGreg Clayton                 if (style_char)
962*554f68d3SGreg Clayton                     special_directions_stream.Printf("%%%c", style_char);
963*554f68d3SGreg Clayton             }
964*554f68d3SGreg Clayton             special_directions_stream.PutChar('}');
965*554f68d3SGreg Clayton             special_directions = llvm::StringRef(special_directions_stream.GetString());
966*554f68d3SGreg Clayton         }
967*554f68d3SGreg Clayton 
968*554f68d3SGreg Clayton         // let us display items index_lower thru index_higher of this array
969*554f68d3SGreg Clayton         s.PutChar('[');
970*554f68d3SGreg Clayton 
971*554f68d3SGreg Clayton         if (index_higher < 0)
972*554f68d3SGreg Clayton             index_higher = valobj->GetNumChildren() - 1;
973*554f68d3SGreg Clayton 
974*554f68d3SGreg Clayton         uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
975*554f68d3SGreg Clayton 
976*554f68d3SGreg Clayton         bool success = true;
977*554f68d3SGreg Clayton         for (int64_t index = index_lower;index<=index_higher; ++index)
978*554f68d3SGreg Clayton         {
979*554f68d3SGreg Clayton             ValueObject* item = ExpandIndexedExpression (target,
980*554f68d3SGreg Clayton                                                          index,
981*554f68d3SGreg Clayton                                                          exe_ctx->GetFramePtr(),
982*554f68d3SGreg Clayton                                                          false).get();
983*554f68d3SGreg Clayton 
984*554f68d3SGreg Clayton             if (!item)
985*554f68d3SGreg Clayton             {
986*554f68d3SGreg Clayton                 if (log)
987*554f68d3SGreg Clayton                     log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64, index);
988*554f68d3SGreg Clayton             }
989*554f68d3SGreg Clayton             else
990*554f68d3SGreg Clayton             {
991*554f68d3SGreg Clayton                 if (log)
992*554f68d3SGreg Clayton                     log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions.data() ? special_directions.data() : "");
993*554f68d3SGreg Clayton             }
994*554f68d3SGreg Clayton 
995*554f68d3SGreg Clayton             if (special_directions.empty())
996*554f68d3SGreg Clayton             {
997*554f68d3SGreg Clayton                 success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format);
998*554f68d3SGreg Clayton             }
999*554f68d3SGreg Clayton             else
1000*554f68d3SGreg Clayton             {
1001*554f68d3SGreg Clayton                 success &= FormatEntity::FormatStringRef(special_directions, s, sc, exe_ctx, NULL, item, false, false);
1002*554f68d3SGreg Clayton             }
1003*554f68d3SGreg Clayton 
1004*554f68d3SGreg Clayton             if (--max_num_children == 0)
1005*554f68d3SGreg Clayton             {
1006*554f68d3SGreg Clayton                 s.PutCString(", ...");
1007*554f68d3SGreg Clayton                 break;
1008*554f68d3SGreg Clayton             }
1009*554f68d3SGreg Clayton 
1010*554f68d3SGreg Clayton             if (index < index_higher)
1011*554f68d3SGreg Clayton                 s.PutChar(',');
1012*554f68d3SGreg Clayton         }
1013*554f68d3SGreg Clayton         s.PutChar(']');
1014*554f68d3SGreg Clayton         return success;
1015*554f68d3SGreg Clayton     }
1016*554f68d3SGreg Clayton 
1017*554f68d3SGreg Clayton }
1018*554f68d3SGreg Clayton 
1019*554f68d3SGreg Clayton static bool
1020*554f68d3SGreg Clayton DumpRegister (Stream &s,
1021*554f68d3SGreg Clayton               StackFrame *frame,
1022*554f68d3SGreg Clayton               const char *reg_name,
1023*554f68d3SGreg Clayton               Format format)
1024*554f68d3SGreg Clayton 
1025*554f68d3SGreg Clayton {
1026*554f68d3SGreg Clayton     if (frame)
1027*554f68d3SGreg Clayton     {
1028*554f68d3SGreg Clayton         RegisterContext *reg_ctx = frame->GetRegisterContext().get();
1029*554f68d3SGreg Clayton 
1030*554f68d3SGreg Clayton         if (reg_ctx)
1031*554f68d3SGreg Clayton         {
1032*554f68d3SGreg Clayton             const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
1033*554f68d3SGreg Clayton             if (reg_info)
1034*554f68d3SGreg Clayton             {
1035*554f68d3SGreg Clayton                 RegisterValue reg_value;
1036*554f68d3SGreg Clayton                 if (reg_ctx->ReadRegister (reg_info, reg_value))
1037*554f68d3SGreg Clayton                 {
1038*554f68d3SGreg Clayton                     reg_value.Dump(&s, reg_info, false, false, format);
1039*554f68d3SGreg Clayton                     return true;
1040*554f68d3SGreg Clayton                 }
1041*554f68d3SGreg Clayton             }
1042*554f68d3SGreg Clayton         }
1043*554f68d3SGreg Clayton     }
1044*554f68d3SGreg Clayton     return false;
1045*554f68d3SGreg Clayton }
1046*554f68d3SGreg Clayton 
1047*554f68d3SGreg Clayton static bool
1048*554f68d3SGreg Clayton FormatThreadExtendedInfoRecurse(const FormatEntity::Entry &entry,
1049*554f68d3SGreg Clayton                                 const StructuredData::ObjectSP &thread_info_dictionary,
1050*554f68d3SGreg Clayton                                 const SymbolContext *sc,
1051*554f68d3SGreg Clayton                                 const ExecutionContext *exe_ctx,
1052*554f68d3SGreg Clayton                                 Stream &s)
1053*554f68d3SGreg Clayton {
1054*554f68d3SGreg Clayton     llvm::StringRef path(entry.string);
1055*554f68d3SGreg Clayton 
1056*554f68d3SGreg Clayton     StructuredData::ObjectSP value = thread_info_dictionary->GetObjectForDotSeparatedPath (path);
1057*554f68d3SGreg Clayton 
1058*554f68d3SGreg Clayton     if (value.get())
1059*554f68d3SGreg Clayton     {
1060*554f68d3SGreg Clayton         if (value->GetType() == StructuredData::Type::eTypeInteger)
1061*554f68d3SGreg Clayton         {
1062*554f68d3SGreg Clayton             const char *token_format = "0x%4.4" PRIx64;
1063*554f68d3SGreg Clayton             if (!entry.printf_format.empty())
1064*554f68d3SGreg Clayton                 token_format = entry.printf_format.c_str();
1065*554f68d3SGreg Clayton             s.Printf(token_format, value->GetAsInteger()->GetValue());
1066*554f68d3SGreg Clayton             return true;
1067*554f68d3SGreg Clayton         }
1068*554f68d3SGreg Clayton         else if (value->GetType() == StructuredData::Type::eTypeFloat)
1069*554f68d3SGreg Clayton         {
1070*554f68d3SGreg Clayton             s.Printf ("%f", value->GetAsFloat()->GetValue());
1071*554f68d3SGreg Clayton             return true;
1072*554f68d3SGreg Clayton         }
1073*554f68d3SGreg Clayton         else if (value->GetType() == StructuredData::Type::eTypeString)
1074*554f68d3SGreg Clayton         {
1075*554f68d3SGreg Clayton             s.Printf("%s", value->GetAsString()->GetValue().c_str());
1076*554f68d3SGreg Clayton             return true;
1077*554f68d3SGreg Clayton         }
1078*554f68d3SGreg Clayton         else if (value->GetType() == StructuredData::Type::eTypeArray)
1079*554f68d3SGreg Clayton         {
1080*554f68d3SGreg Clayton             if (value->GetAsArray()->GetSize() > 0)
1081*554f68d3SGreg Clayton             {
1082*554f68d3SGreg Clayton                 s.Printf ("%zu", value->GetAsArray()->GetSize());
1083*554f68d3SGreg Clayton                 return true;
1084*554f68d3SGreg Clayton             }
1085*554f68d3SGreg Clayton         }
1086*554f68d3SGreg Clayton         else if (value->GetType() == StructuredData::Type::eTypeDictionary)
1087*554f68d3SGreg Clayton         {
1088*554f68d3SGreg Clayton             s.Printf ("%zu", value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
1089*554f68d3SGreg Clayton             return true;
1090*554f68d3SGreg Clayton         }
1091*554f68d3SGreg Clayton     }
1092*554f68d3SGreg Clayton 
1093*554f68d3SGreg Clayton     return false;
1094*554f68d3SGreg Clayton }
1095*554f68d3SGreg Clayton 
1096*554f68d3SGreg Clayton 
1097*554f68d3SGreg Clayton static inline bool
1098*554f68d3SGreg Clayton IsToken(const char *var_name_begin, const char *var)
1099*554f68d3SGreg Clayton {
1100*554f68d3SGreg Clayton     return (::strncmp (var_name_begin, var, strlen(var)) == 0);
1101*554f68d3SGreg Clayton }
1102*554f68d3SGreg Clayton 
1103*554f68d3SGreg Clayton bool
1104*554f68d3SGreg Clayton FormatEntity::FormatStringRef (const llvm::StringRef &format_str,
1105*554f68d3SGreg Clayton                                Stream &s,
1106*554f68d3SGreg Clayton                                const SymbolContext *sc,
1107*554f68d3SGreg Clayton                                const ExecutionContext *exe_ctx,
1108*554f68d3SGreg Clayton                                const Address *addr,
1109*554f68d3SGreg Clayton                                ValueObject* valobj,
1110*554f68d3SGreg Clayton                                bool function_changed,
1111*554f68d3SGreg Clayton                                bool initial_function)
1112*554f68d3SGreg Clayton {
1113*554f68d3SGreg Clayton     if (!format_str.empty())
1114*554f68d3SGreg Clayton     {
1115*554f68d3SGreg Clayton         FormatEntity::Entry root;
1116*554f68d3SGreg Clayton         Error error = FormatEntity::Parse(format_str, root);
1117*554f68d3SGreg Clayton         if (error.Success())
1118*554f68d3SGreg Clayton         {
1119*554f68d3SGreg Clayton             return FormatEntity::Format (root,
1120*554f68d3SGreg Clayton                                          s,
1121*554f68d3SGreg Clayton                                          sc,
1122*554f68d3SGreg Clayton                                          exe_ctx,
1123*554f68d3SGreg Clayton                                          addr,
1124*554f68d3SGreg Clayton                                          valobj,
1125*554f68d3SGreg Clayton                                          function_changed,
1126*554f68d3SGreg Clayton                                          initial_function);
1127*554f68d3SGreg Clayton         }
1128*554f68d3SGreg Clayton     }
1129*554f68d3SGreg Clayton     return false;
1130*554f68d3SGreg Clayton 
1131*554f68d3SGreg Clayton }
1132*554f68d3SGreg Clayton bool
1133*554f68d3SGreg Clayton FormatEntity::FormatCString (const char *format,
1134*554f68d3SGreg Clayton                              Stream &s,
1135*554f68d3SGreg Clayton                              const SymbolContext *sc,
1136*554f68d3SGreg Clayton                              const ExecutionContext *exe_ctx,
1137*554f68d3SGreg Clayton                              const Address *addr,
1138*554f68d3SGreg Clayton                              ValueObject* valobj,
1139*554f68d3SGreg Clayton                              bool function_changed,
1140*554f68d3SGreg Clayton                              bool initial_function)
1141*554f68d3SGreg Clayton {
1142*554f68d3SGreg Clayton     if (format && format[0])
1143*554f68d3SGreg Clayton     {
1144*554f68d3SGreg Clayton         FormatEntity::Entry root;
1145*554f68d3SGreg Clayton         llvm::StringRef format_str(format);
1146*554f68d3SGreg Clayton         Error error = FormatEntity::Parse(format_str, root);
1147*554f68d3SGreg Clayton         if (error.Success())
1148*554f68d3SGreg Clayton         {
1149*554f68d3SGreg Clayton             return FormatEntity::Format (root,
1150*554f68d3SGreg Clayton                                          s,
1151*554f68d3SGreg Clayton                                          sc,
1152*554f68d3SGreg Clayton                                          exe_ctx,
1153*554f68d3SGreg Clayton                                          addr,
1154*554f68d3SGreg Clayton                                          valobj,
1155*554f68d3SGreg Clayton                                          function_changed,
1156*554f68d3SGreg Clayton                                          initial_function);
1157*554f68d3SGreg Clayton         }
1158*554f68d3SGreg Clayton     }
1159*554f68d3SGreg Clayton     return false;
1160*554f68d3SGreg Clayton }
1161*554f68d3SGreg Clayton 
1162*554f68d3SGreg Clayton bool
1163*554f68d3SGreg Clayton FormatEntity::Format (const Entry &entry,
1164*554f68d3SGreg Clayton                       Stream &s,
1165*554f68d3SGreg Clayton                       const SymbolContext *sc,
1166*554f68d3SGreg Clayton                       const ExecutionContext *exe_ctx,
1167*554f68d3SGreg Clayton                       const Address *addr,
1168*554f68d3SGreg Clayton                       ValueObject* valobj,
1169*554f68d3SGreg Clayton                       bool function_changed,
1170*554f68d3SGreg Clayton                       bool initial_function)
1171*554f68d3SGreg Clayton {
1172*554f68d3SGreg Clayton     switch (entry.type)
1173*554f68d3SGreg Clayton     {
1174*554f68d3SGreg Clayton         case Entry::Type::Invalid:
1175*554f68d3SGreg Clayton         case Entry::Type::ParentNumber: // Only used for FormatEntity::Entry::Definition encoding
1176*554f68d3SGreg Clayton         case Entry::Type::ParentString: // Only used for FormatEntity::Entry::Definition encoding
1177*554f68d3SGreg Clayton         case Entry::Type::InsertString: // Only used for FormatEntity::Entry::Definition encoding
1178*554f68d3SGreg Clayton             return false;
1179*554f68d3SGreg Clayton 
1180*554f68d3SGreg Clayton         case Entry::Type::Root:
1181*554f68d3SGreg Clayton             for (const auto &child : entry.children)
1182*554f68d3SGreg Clayton             {
1183*554f68d3SGreg Clayton                 if (Format (child,
1184*554f68d3SGreg Clayton                             s,
1185*554f68d3SGreg Clayton                             sc,
1186*554f68d3SGreg Clayton                             exe_ctx,
1187*554f68d3SGreg Clayton                             addr,
1188*554f68d3SGreg Clayton                             valobj,
1189*554f68d3SGreg Clayton                             function_changed,
1190*554f68d3SGreg Clayton                             initial_function) == false)
1191*554f68d3SGreg Clayton                 {
1192*554f68d3SGreg Clayton                     return false; // If any item of root fails, then the formatting fails
1193*554f68d3SGreg Clayton                 }
1194*554f68d3SGreg Clayton             }
1195*554f68d3SGreg Clayton             return true; // Only return true if all items succeeded
1196*554f68d3SGreg Clayton 
1197*554f68d3SGreg Clayton         case Entry::Type::String:
1198*554f68d3SGreg Clayton             s.PutCString(entry.string.c_str());
1199*554f68d3SGreg Clayton             return true;
1200*554f68d3SGreg Clayton 
1201*554f68d3SGreg Clayton         case Entry::Type::Scope:
1202*554f68d3SGreg Clayton             {
1203*554f68d3SGreg Clayton                 StreamString scope_stream;
1204*554f68d3SGreg Clayton                 bool success = false;
1205*554f68d3SGreg Clayton                 for (const auto &child : entry.children)
1206*554f68d3SGreg Clayton                 {
1207*554f68d3SGreg Clayton                     success = Format (child, scope_stream, sc, exe_ctx, addr, valobj, function_changed, initial_function);
1208*554f68d3SGreg Clayton                     if (!success)
1209*554f68d3SGreg Clayton                         break;
1210*554f68d3SGreg Clayton                 }
1211*554f68d3SGreg Clayton                 // Only if all items in a scope succeed, then do we
1212*554f68d3SGreg Clayton                 // print the output into the main stream
1213*554f68d3SGreg Clayton                 if (success)
1214*554f68d3SGreg Clayton                     s.Write(scope_stream.GetString().data(), scope_stream.GetString().size());
1215*554f68d3SGreg Clayton             }
1216*554f68d3SGreg Clayton             return true; // Scopes always successfully print themselves
1217*554f68d3SGreg Clayton 
1218*554f68d3SGreg Clayton         case Entry::Type::Variable:
1219*554f68d3SGreg Clayton         case Entry::Type::VariableSynthetic:
1220*554f68d3SGreg Clayton         case Entry::Type::ScriptVariable:
1221*554f68d3SGreg Clayton         case Entry::Type::ScriptVariableSynthetic:
1222*554f68d3SGreg Clayton             if (DumpValue(s, sc, exe_ctx, entry, valobj))
1223*554f68d3SGreg Clayton                 return true;
1224*554f68d3SGreg Clayton             return false;
1225*554f68d3SGreg Clayton 
1226*554f68d3SGreg Clayton         case Entry::Type::AddressFile:
1227*554f68d3SGreg Clayton         case Entry::Type::AddressLoad:
1228*554f68d3SGreg Clayton         case Entry::Type::AddressLoadOrFile:
1229*554f68d3SGreg Clayton             if (addr && addr->IsValid() && DumpAddress(s, sc, exe_ctx, *addr, entry.type == Entry::Type::AddressLoadOrFile))
1230*554f68d3SGreg Clayton                 return true;
1231*554f68d3SGreg Clayton             return false;
1232*554f68d3SGreg Clayton 
1233*554f68d3SGreg Clayton         case Entry::Type::ProcessID:
1234*554f68d3SGreg Clayton             if (exe_ctx)
1235*554f68d3SGreg Clayton             {
1236*554f68d3SGreg Clayton                 Process *process = exe_ctx->GetProcessPtr();
1237*554f68d3SGreg Clayton                 if (process)
1238*554f68d3SGreg Clayton                 {
1239*554f68d3SGreg Clayton                     const char *format = "%" PRIu64;
1240*554f68d3SGreg Clayton                     if (!entry.printf_format.empty())
1241*554f68d3SGreg Clayton                         format = entry.printf_format.c_str();
1242*554f68d3SGreg Clayton                     s.Printf(format, process->GetID());
1243*554f68d3SGreg Clayton                     return true;
1244*554f68d3SGreg Clayton                 }
1245*554f68d3SGreg Clayton             }
1246*554f68d3SGreg Clayton             return false;
1247*554f68d3SGreg Clayton 
1248*554f68d3SGreg Clayton         case Entry::Type::ProcessFile:
1249*554f68d3SGreg Clayton             if (exe_ctx)
1250*554f68d3SGreg Clayton             {
1251*554f68d3SGreg Clayton                 Process *process = exe_ctx->GetProcessPtr();
1252*554f68d3SGreg Clayton                 if (process)
1253*554f68d3SGreg Clayton                 {
1254*554f68d3SGreg Clayton                     Module *exe_module = process->GetTarget().GetExecutableModulePointer();
1255*554f68d3SGreg Clayton                     if (exe_module)
1256*554f68d3SGreg Clayton                     {
1257*554f68d3SGreg Clayton                         if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number))
1258*554f68d3SGreg Clayton                             return true;
1259*554f68d3SGreg Clayton                     }
1260*554f68d3SGreg Clayton                 }
1261*554f68d3SGreg Clayton             }
1262*554f68d3SGreg Clayton             return false;
1263*554f68d3SGreg Clayton 
1264*554f68d3SGreg Clayton         case Entry::Type::ScriptProcess:
1265*554f68d3SGreg Clayton             if (exe_ctx)
1266*554f68d3SGreg Clayton             {
1267*554f68d3SGreg Clayton                 Process *process = exe_ctx->GetProcessPtr();
1268*554f68d3SGreg Clayton                 if (process)
1269*554f68d3SGreg Clayton                     return RunScriptFormatKeyword (s, sc, exe_ctx, process, entry.string.c_str());
1270*554f68d3SGreg Clayton             }
1271*554f68d3SGreg Clayton             return false;
1272*554f68d3SGreg Clayton 
1273*554f68d3SGreg Clayton 
1274*554f68d3SGreg Clayton         case Entry::Type::ThreadID:
1275*554f68d3SGreg Clayton             if (exe_ctx)
1276*554f68d3SGreg Clayton             {
1277*554f68d3SGreg Clayton                 Thread *thread = exe_ctx->GetThreadPtr();
1278*554f68d3SGreg Clayton                 if (thread)
1279*554f68d3SGreg Clayton                 {
1280*554f68d3SGreg Clayton                     const char *format = "0x%4.4" PRIx64;
1281*554f68d3SGreg Clayton                     if (!entry.printf_format.empty())
1282*554f68d3SGreg Clayton                     {
1283*554f68d3SGreg Clayton                         // Watch for the special "tid" format...
1284*554f68d3SGreg Clayton                         if (entry.printf_format == "tid")
1285*554f68d3SGreg Clayton                         {
1286*554f68d3SGreg Clayton                             bool handled = false;
1287*554f68d3SGreg Clayton                             Target &target = thread->GetProcess()->GetTarget();
1288*554f68d3SGreg Clayton                             ArchSpec arch (target.GetArchitecture ());
1289*554f68d3SGreg Clayton                             llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS;
1290*554f68d3SGreg Clayton                             if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux))
1291*554f68d3SGreg Clayton                             {
1292*554f68d3SGreg Clayton                                 handled = true;
1293*554f68d3SGreg Clayton                                 format = "%" PRIu64;
1294*554f68d3SGreg Clayton                             }
1295*554f68d3SGreg Clayton                         }
1296*554f68d3SGreg Clayton                         else
1297*554f68d3SGreg Clayton                         {
1298*554f68d3SGreg Clayton                             format = entry.printf_format.c_str();
1299*554f68d3SGreg Clayton                         }
1300*554f68d3SGreg Clayton                     }
1301*554f68d3SGreg Clayton                     s.Printf(format, thread->GetID());
1302*554f68d3SGreg Clayton                     return true;
1303*554f68d3SGreg Clayton                 }
1304*554f68d3SGreg Clayton             }
1305*554f68d3SGreg Clayton             return false;
1306*554f68d3SGreg Clayton 
1307*554f68d3SGreg Clayton         case Entry::Type::ThreadProtocolID:
1308*554f68d3SGreg Clayton             if (exe_ctx)
1309*554f68d3SGreg Clayton             {
1310*554f68d3SGreg Clayton                 Thread *thread = exe_ctx->GetThreadPtr();
1311*554f68d3SGreg Clayton                 if (thread)
1312*554f68d3SGreg Clayton                 {
1313*554f68d3SGreg Clayton                     const char *format = "0x%4.4" PRIx64;
1314*554f68d3SGreg Clayton                     if (!entry.printf_format.empty())
1315*554f68d3SGreg Clayton                         format = entry.printf_format.c_str();
1316*554f68d3SGreg Clayton                     s.Printf(format, thread->GetProtocolID());
1317*554f68d3SGreg Clayton                     return true;
1318*554f68d3SGreg Clayton                 }
1319*554f68d3SGreg Clayton             }
1320*554f68d3SGreg Clayton             return false;
1321*554f68d3SGreg Clayton 
1322*554f68d3SGreg Clayton         case Entry::Type::ThreadIndexID:
1323*554f68d3SGreg Clayton             if (exe_ctx)
1324*554f68d3SGreg Clayton             {
1325*554f68d3SGreg Clayton                 Thread *thread = exe_ctx->GetThreadPtr();
1326*554f68d3SGreg Clayton                 if (thread)
1327*554f68d3SGreg Clayton                 {
1328*554f68d3SGreg Clayton                     const char *format = "%" PRIu32;
1329*554f68d3SGreg Clayton                     if (!entry.printf_format.empty())
1330*554f68d3SGreg Clayton                         format = entry.printf_format.c_str();
1331*554f68d3SGreg Clayton                     s.Printf(format, thread->GetIndexID());
1332*554f68d3SGreg Clayton                     return true;
1333*554f68d3SGreg Clayton                 }
1334*554f68d3SGreg Clayton             }
1335*554f68d3SGreg Clayton             return false;
1336*554f68d3SGreg Clayton 
1337*554f68d3SGreg Clayton         case Entry::Type::ThreadName:
1338*554f68d3SGreg Clayton             if (exe_ctx)
1339*554f68d3SGreg Clayton             {
1340*554f68d3SGreg Clayton                 Thread *thread = exe_ctx->GetThreadPtr();
1341*554f68d3SGreg Clayton                 if (thread)
1342*554f68d3SGreg Clayton                 {
1343*554f68d3SGreg Clayton                     const char *cstr = thread->GetName();
1344*554f68d3SGreg Clayton                     if (cstr && cstr[0])
1345*554f68d3SGreg Clayton                     {
1346*554f68d3SGreg Clayton                         s.PutCString(cstr);
1347*554f68d3SGreg Clayton                         return true;
1348*554f68d3SGreg Clayton                     }
1349*554f68d3SGreg Clayton                 }
1350*554f68d3SGreg Clayton             }
1351*554f68d3SGreg Clayton             return false;
1352*554f68d3SGreg Clayton 
1353*554f68d3SGreg Clayton         case Entry::Type::ThreadQueue:
1354*554f68d3SGreg Clayton             if (exe_ctx)
1355*554f68d3SGreg Clayton             {
1356*554f68d3SGreg Clayton                 Thread *thread = exe_ctx->GetThreadPtr();
1357*554f68d3SGreg Clayton                 if (thread)
1358*554f68d3SGreg Clayton                 {
1359*554f68d3SGreg Clayton                     const char *cstr = thread->GetQueueName();
1360*554f68d3SGreg Clayton                     if (cstr && cstr[0])
1361*554f68d3SGreg Clayton                     {
1362*554f68d3SGreg Clayton                         s.PutCString(cstr);
1363*554f68d3SGreg Clayton                         return true;
1364*554f68d3SGreg Clayton                     }
1365*554f68d3SGreg Clayton                 }
1366*554f68d3SGreg Clayton             }
1367*554f68d3SGreg Clayton             return false;
1368*554f68d3SGreg Clayton 
1369*554f68d3SGreg Clayton         case Entry::Type::ThreadStopReason:
1370*554f68d3SGreg Clayton             if (exe_ctx)
1371*554f68d3SGreg Clayton             {
1372*554f68d3SGreg Clayton                 Thread *thread = exe_ctx->GetThreadPtr();
1373*554f68d3SGreg Clayton                 if (thread)
1374*554f68d3SGreg Clayton                 {
1375*554f68d3SGreg Clayton                     StopInfoSP stop_info_sp = thread->GetStopInfo ();
1376*554f68d3SGreg Clayton                     if (stop_info_sp && stop_info_sp->IsValid())
1377*554f68d3SGreg Clayton                     {
1378*554f68d3SGreg Clayton                         const char *cstr = stop_info_sp->GetDescription();
1379*554f68d3SGreg Clayton                         if (cstr && cstr[0])
1380*554f68d3SGreg Clayton                         {
1381*554f68d3SGreg Clayton                             s.PutCString(cstr);
1382*554f68d3SGreg Clayton                             return true;
1383*554f68d3SGreg Clayton                         }
1384*554f68d3SGreg Clayton                     }
1385*554f68d3SGreg Clayton                 }
1386*554f68d3SGreg Clayton             }
1387*554f68d3SGreg Clayton             return false;
1388*554f68d3SGreg Clayton 
1389*554f68d3SGreg Clayton         case Entry::Type::ThreadReturnValue:
1390*554f68d3SGreg Clayton             if (exe_ctx)
1391*554f68d3SGreg Clayton             {
1392*554f68d3SGreg Clayton                 Thread *thread = exe_ctx->GetThreadPtr();
1393*554f68d3SGreg Clayton                 if (thread)
1394*554f68d3SGreg Clayton                 {
1395*554f68d3SGreg Clayton                     StopInfoSP stop_info_sp = thread->GetStopInfo ();
1396*554f68d3SGreg Clayton                     if (stop_info_sp && stop_info_sp->IsValid())
1397*554f68d3SGreg Clayton                     {
1398*554f68d3SGreg Clayton                         ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp);
1399*554f68d3SGreg Clayton                         if (return_valobj_sp)
1400*554f68d3SGreg Clayton                         {
1401*554f68d3SGreg Clayton                             return_valobj_sp->Dump(s);
1402*554f68d3SGreg Clayton                             return true;
1403*554f68d3SGreg Clayton                         }
1404*554f68d3SGreg Clayton                     }
1405*554f68d3SGreg Clayton                 }
1406*554f68d3SGreg Clayton             }
1407*554f68d3SGreg Clayton             return false;
1408*554f68d3SGreg Clayton 
1409*554f68d3SGreg Clayton         case Entry::Type::ThreadCompletedExpression:
1410*554f68d3SGreg Clayton             if (exe_ctx)
1411*554f68d3SGreg Clayton             {
1412*554f68d3SGreg Clayton                 Thread *thread = exe_ctx->GetThreadPtr();
1413*554f68d3SGreg Clayton                 if (thread)
1414*554f68d3SGreg Clayton                 {
1415*554f68d3SGreg Clayton                     StopInfoSP stop_info_sp = thread->GetStopInfo ();
1416*554f68d3SGreg Clayton                     if (stop_info_sp && stop_info_sp->IsValid())
1417*554f68d3SGreg Clayton                     {
1418*554f68d3SGreg Clayton                         ClangExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp);
1419*554f68d3SGreg Clayton                         if (expression_var_sp && expression_var_sp->GetValueObject())
1420*554f68d3SGreg Clayton                         {
1421*554f68d3SGreg Clayton                             expression_var_sp->GetValueObject()->Dump(s);
1422*554f68d3SGreg Clayton                             return true;
1423*554f68d3SGreg Clayton                         }
1424*554f68d3SGreg Clayton                     }
1425*554f68d3SGreg Clayton                 }
1426*554f68d3SGreg Clayton             }
1427*554f68d3SGreg Clayton             return false;
1428*554f68d3SGreg Clayton 
1429*554f68d3SGreg Clayton         case Entry::Type::ScriptThread:
1430*554f68d3SGreg Clayton             if (exe_ctx)
1431*554f68d3SGreg Clayton             {
1432*554f68d3SGreg Clayton                 Thread *thread = exe_ctx->GetThreadPtr();
1433*554f68d3SGreg Clayton                 if (thread)
1434*554f68d3SGreg Clayton                     return RunScriptFormatKeyword (s, sc, exe_ctx, thread, entry.string.c_str());
1435*554f68d3SGreg Clayton             }
1436*554f68d3SGreg Clayton             return false;
1437*554f68d3SGreg Clayton 
1438*554f68d3SGreg Clayton         case Entry::Type::ThreadInfo:
1439*554f68d3SGreg Clayton             if (exe_ctx)
1440*554f68d3SGreg Clayton             {
1441*554f68d3SGreg Clayton                 Thread *thread = exe_ctx->GetThreadPtr();
1442*554f68d3SGreg Clayton                 if (thread)
1443*554f68d3SGreg Clayton                 {
1444*554f68d3SGreg Clayton                     StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
1445*554f68d3SGreg Clayton                     if (object_sp && object_sp->GetType() == StructuredData::Type::eTypeDictionary)
1446*554f68d3SGreg Clayton                     {
1447*554f68d3SGreg Clayton                         if (FormatThreadExtendedInfoRecurse (entry, object_sp, sc, exe_ctx, s))
1448*554f68d3SGreg Clayton                             return true;
1449*554f68d3SGreg Clayton                     }
1450*554f68d3SGreg Clayton                 }
1451*554f68d3SGreg Clayton             }
1452*554f68d3SGreg Clayton             return false;
1453*554f68d3SGreg Clayton 
1454*554f68d3SGreg Clayton         case Entry::Type::TargetArch:
1455*554f68d3SGreg Clayton             if (exe_ctx)
1456*554f68d3SGreg Clayton             {
1457*554f68d3SGreg Clayton                 Target *target = exe_ctx->GetTargetPtr();
1458*554f68d3SGreg Clayton                 if (target)
1459*554f68d3SGreg Clayton                 {
1460*554f68d3SGreg Clayton                     const ArchSpec &arch = target->GetArchitecture ();
1461*554f68d3SGreg Clayton                     if (arch.IsValid())
1462*554f68d3SGreg Clayton                     {
1463*554f68d3SGreg Clayton                         s.PutCString (arch.GetArchitectureName());
1464*554f68d3SGreg Clayton                         return true;
1465*554f68d3SGreg Clayton                     }
1466*554f68d3SGreg Clayton                 }
1467*554f68d3SGreg Clayton             }
1468*554f68d3SGreg Clayton             return false;
1469*554f68d3SGreg Clayton 
1470*554f68d3SGreg Clayton         case Entry::Type::ScriptTarget:
1471*554f68d3SGreg Clayton             if (exe_ctx)
1472*554f68d3SGreg Clayton             {
1473*554f68d3SGreg Clayton                 Target *target = exe_ctx->GetTargetPtr();
1474*554f68d3SGreg Clayton                 if (target)
1475*554f68d3SGreg Clayton                     return RunScriptFormatKeyword (s, sc, exe_ctx, target, entry.string.c_str());
1476*554f68d3SGreg Clayton             }
1477*554f68d3SGreg Clayton             return false;
1478*554f68d3SGreg Clayton 
1479*554f68d3SGreg Clayton         case Entry::Type::ModuleFile:
1480*554f68d3SGreg Clayton             if (sc)
1481*554f68d3SGreg Clayton             {
1482*554f68d3SGreg Clayton                 Module *module = sc->module_sp.get();
1483*554f68d3SGreg Clayton                 if (module)
1484*554f68d3SGreg Clayton                 {
1485*554f68d3SGreg Clayton                     if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number))
1486*554f68d3SGreg Clayton                         return true;
1487*554f68d3SGreg Clayton                 }
1488*554f68d3SGreg Clayton             }
1489*554f68d3SGreg Clayton             return false;
1490*554f68d3SGreg Clayton 
1491*554f68d3SGreg Clayton         case Entry::Type::File:
1492*554f68d3SGreg Clayton             if (sc)
1493*554f68d3SGreg Clayton             {
1494*554f68d3SGreg Clayton                 CompileUnit *cu = sc->comp_unit;
1495*554f68d3SGreg Clayton                 if (cu)
1496*554f68d3SGreg Clayton                 {
1497*554f68d3SGreg Clayton                     // CompileUnit is a FileSpec
1498*554f68d3SGreg Clayton                     if (DumpFile(s, *cu, (FileKind)entry.number))
1499*554f68d3SGreg Clayton                         return true;
1500*554f68d3SGreg Clayton                 }
1501*554f68d3SGreg Clayton             }
1502*554f68d3SGreg Clayton             return false;
1503*554f68d3SGreg Clayton 
1504*554f68d3SGreg Clayton         case Entry::Type::FrameIndex:
1505*554f68d3SGreg Clayton             if (exe_ctx)
1506*554f68d3SGreg Clayton             {
1507*554f68d3SGreg Clayton                 StackFrame *frame = exe_ctx->GetFramePtr();
1508*554f68d3SGreg Clayton                 if (frame)
1509*554f68d3SGreg Clayton                 {
1510*554f68d3SGreg Clayton                     const char *format = "%" PRIu32;
1511*554f68d3SGreg Clayton                     if (!entry.printf_format.empty())
1512*554f68d3SGreg Clayton                         format = entry.printf_format.c_str();
1513*554f68d3SGreg Clayton                     s.Printf(format, frame->GetFrameIndex());
1514*554f68d3SGreg Clayton                     return true;
1515*554f68d3SGreg Clayton                 }
1516*554f68d3SGreg Clayton             }
1517*554f68d3SGreg Clayton             return false;
1518*554f68d3SGreg Clayton 
1519*554f68d3SGreg Clayton         case Entry::Type::FrameRegisterPC:
1520*554f68d3SGreg Clayton             if (exe_ctx)
1521*554f68d3SGreg Clayton             {
1522*554f68d3SGreg Clayton                 StackFrame *frame = exe_ctx->GetFramePtr();
1523*554f68d3SGreg Clayton                 if (frame)
1524*554f68d3SGreg Clayton                 {
1525*554f68d3SGreg Clayton                     const Address &pc_addr = frame->GetFrameCodeAddress();
1526*554f68d3SGreg Clayton                     if (pc_addr.IsValid())
1527*554f68d3SGreg Clayton                     {
1528*554f68d3SGreg Clayton                         if (DumpAddress(s, sc, exe_ctx, pc_addr, false))
1529*554f68d3SGreg Clayton                             return true;
1530*554f68d3SGreg Clayton                     }
1531*554f68d3SGreg Clayton                 }
1532*554f68d3SGreg Clayton             }
1533*554f68d3SGreg Clayton             return false;
1534*554f68d3SGreg Clayton 
1535*554f68d3SGreg Clayton         case Entry::Type::FrameRegisterSP:
1536*554f68d3SGreg Clayton             if (exe_ctx)
1537*554f68d3SGreg Clayton             {
1538*554f68d3SGreg Clayton                 StackFrame *frame = exe_ctx->GetFramePtr();
1539*554f68d3SGreg Clayton                 if (frame)
1540*554f68d3SGreg Clayton                 {
1541*554f68d3SGreg Clayton                     if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, (lldb::Format)entry.number))
1542*554f68d3SGreg Clayton                         return true;
1543*554f68d3SGreg Clayton                 }
1544*554f68d3SGreg Clayton             }
1545*554f68d3SGreg Clayton             return false;
1546*554f68d3SGreg Clayton 
1547*554f68d3SGreg Clayton         case Entry::Type::FrameRegisterFP:
1548*554f68d3SGreg Clayton             if (exe_ctx)
1549*554f68d3SGreg Clayton             {
1550*554f68d3SGreg Clayton                 StackFrame *frame = exe_ctx->GetFramePtr();
1551*554f68d3SGreg Clayton                 if (frame)
1552*554f68d3SGreg Clayton                 {
1553*554f68d3SGreg Clayton                     if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, (lldb::Format)entry.number))
1554*554f68d3SGreg Clayton                         return true;
1555*554f68d3SGreg Clayton                 }
1556*554f68d3SGreg Clayton             }
1557*554f68d3SGreg Clayton             return false;
1558*554f68d3SGreg Clayton 
1559*554f68d3SGreg Clayton         case Entry::Type::FrameRegisterFlags:
1560*554f68d3SGreg Clayton             if (exe_ctx)
1561*554f68d3SGreg Clayton             {
1562*554f68d3SGreg Clayton                 StackFrame *frame = exe_ctx->GetFramePtr();
1563*554f68d3SGreg Clayton                 if (frame)
1564*554f68d3SGreg Clayton                 {
1565*554f68d3SGreg Clayton                     if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number))
1566*554f68d3SGreg Clayton                         return true;
1567*554f68d3SGreg Clayton                 }
1568*554f68d3SGreg Clayton             }
1569*554f68d3SGreg Clayton             return false;
1570*554f68d3SGreg Clayton 
1571*554f68d3SGreg Clayton 
1572*554f68d3SGreg Clayton         case Entry::Type::FrameRegisterByName:
1573*554f68d3SGreg Clayton             if (exe_ctx)
1574*554f68d3SGreg Clayton             {
1575*554f68d3SGreg Clayton                 StackFrame *frame = exe_ctx->GetFramePtr();
1576*554f68d3SGreg Clayton                 if (frame)
1577*554f68d3SGreg Clayton                 {
1578*554f68d3SGreg Clayton                     if (DumpRegister (s, frame, entry.string.c_str(), (lldb::Format)entry.number))
1579*554f68d3SGreg Clayton                         return true;
1580*554f68d3SGreg Clayton                 }
1581*554f68d3SGreg Clayton             }
1582*554f68d3SGreg Clayton             return false;
1583*554f68d3SGreg Clayton 
1584*554f68d3SGreg Clayton         case Entry::Type::ScriptFrame:
1585*554f68d3SGreg Clayton             if (exe_ctx)
1586*554f68d3SGreg Clayton             {
1587*554f68d3SGreg Clayton                 StackFrame *frame = exe_ctx->GetFramePtr();
1588*554f68d3SGreg Clayton                 if (frame)
1589*554f68d3SGreg Clayton                     return RunScriptFormatKeyword (s, sc, exe_ctx, frame, entry.string.c_str());
1590*554f68d3SGreg Clayton             }
1591*554f68d3SGreg Clayton             return false;
1592*554f68d3SGreg Clayton 
1593*554f68d3SGreg Clayton         case Entry::Type::FunctionID:
1594*554f68d3SGreg Clayton             if (sc)
1595*554f68d3SGreg Clayton             {
1596*554f68d3SGreg Clayton                 if (sc->function)
1597*554f68d3SGreg Clayton                 {
1598*554f68d3SGreg Clayton                     s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID());
1599*554f68d3SGreg Clayton                     return true;
1600*554f68d3SGreg Clayton                 }
1601*554f68d3SGreg Clayton                 else if (sc->symbol)
1602*554f68d3SGreg Clayton                 {
1603*554f68d3SGreg Clayton                     s.Printf("symbol[%u]", sc->symbol->GetID());
1604*554f68d3SGreg Clayton                     return true;
1605*554f68d3SGreg Clayton                 }
1606*554f68d3SGreg Clayton             }
1607*554f68d3SGreg Clayton             return false;
1608*554f68d3SGreg Clayton 
1609*554f68d3SGreg Clayton         case Entry::Type::FunctionDidChange:
1610*554f68d3SGreg Clayton             return function_changed;
1611*554f68d3SGreg Clayton 
1612*554f68d3SGreg Clayton         case Entry::Type::FunctionInitialFunction:
1613*554f68d3SGreg Clayton             return initial_function;
1614*554f68d3SGreg Clayton 
1615*554f68d3SGreg Clayton         case Entry::Type::FunctionName:
1616*554f68d3SGreg Clayton             {
1617*554f68d3SGreg Clayton                 const char *name = NULL;
1618*554f68d3SGreg Clayton                 if (sc->function)
1619*554f68d3SGreg Clayton                     name = sc->function->GetName().AsCString (NULL);
1620*554f68d3SGreg Clayton                 else if (sc->symbol)
1621*554f68d3SGreg Clayton                     name = sc->symbol->GetName().AsCString (NULL);
1622*554f68d3SGreg Clayton                 if (name)
1623*554f68d3SGreg Clayton                 {
1624*554f68d3SGreg Clayton                     s.PutCString(name);
1625*554f68d3SGreg Clayton 
1626*554f68d3SGreg Clayton                     if (sc->block)
1627*554f68d3SGreg Clayton                     {
1628*554f68d3SGreg Clayton                         Block *inline_block = sc->block->GetContainingInlinedBlock ();
1629*554f68d3SGreg Clayton                         if (inline_block)
1630*554f68d3SGreg Clayton                         {
1631*554f68d3SGreg Clayton                             const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo();
1632*554f68d3SGreg Clayton                             if (inline_info)
1633*554f68d3SGreg Clayton                             {
1634*554f68d3SGreg Clayton                                 s.PutCString(" [inlined] ");
1635*554f68d3SGreg Clayton                                 inline_info->GetName().Dump(&s);
1636*554f68d3SGreg Clayton                             }
1637*554f68d3SGreg Clayton                         }
1638*554f68d3SGreg Clayton                     }
1639*554f68d3SGreg Clayton                     return true;
1640*554f68d3SGreg Clayton                 }
1641*554f68d3SGreg Clayton             }
1642*554f68d3SGreg Clayton             return false;
1643*554f68d3SGreg Clayton 
1644*554f68d3SGreg Clayton         case Entry::Type::FunctionNameNoArgs:
1645*554f68d3SGreg Clayton             {
1646*554f68d3SGreg Clayton                 ConstString name;
1647*554f68d3SGreg Clayton                 if (sc->function)
1648*554f68d3SGreg Clayton                     name = sc->function->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments);
1649*554f68d3SGreg Clayton                 else if (sc->symbol)
1650*554f68d3SGreg Clayton                     name = sc->symbol->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments);
1651*554f68d3SGreg Clayton                 if (name)
1652*554f68d3SGreg Clayton                 {
1653*554f68d3SGreg Clayton                     s.PutCString(name.GetCString());
1654*554f68d3SGreg Clayton                     return true;
1655*554f68d3SGreg Clayton                 }
1656*554f68d3SGreg Clayton             }
1657*554f68d3SGreg Clayton             return false;
1658*554f68d3SGreg Clayton 
1659*554f68d3SGreg Clayton         case Entry::Type::FunctionNameWithArgs:
1660*554f68d3SGreg Clayton             {
1661*554f68d3SGreg Clayton                 // Print the function name with arguments in it
1662*554f68d3SGreg Clayton                 if (sc->function)
1663*554f68d3SGreg Clayton                 {
1664*554f68d3SGreg Clayton                     ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL;
1665*554f68d3SGreg Clayton                     const char *cstr = sc->function->GetName().AsCString (NULL);
1666*554f68d3SGreg Clayton                     if (cstr)
1667*554f68d3SGreg Clayton                     {
1668*554f68d3SGreg Clayton                         const InlineFunctionInfo *inline_info = NULL;
1669*554f68d3SGreg Clayton                         VariableListSP variable_list_sp;
1670*554f68d3SGreg Clayton                         bool get_function_vars = true;
1671*554f68d3SGreg Clayton                         if (sc->block)
1672*554f68d3SGreg Clayton                         {
1673*554f68d3SGreg Clayton                             Block *inline_block = sc->block->GetContainingInlinedBlock ();
1674*554f68d3SGreg Clayton 
1675*554f68d3SGreg Clayton                             if (inline_block)
1676*554f68d3SGreg Clayton                             {
1677*554f68d3SGreg Clayton                                 get_function_vars = false;
1678*554f68d3SGreg Clayton                                 inline_info = sc->block->GetInlinedFunctionInfo();
1679*554f68d3SGreg Clayton                                 if (inline_info)
1680*554f68d3SGreg Clayton                                     variable_list_sp = inline_block->GetBlockVariableList (true);
1681*554f68d3SGreg Clayton                             }
1682*554f68d3SGreg Clayton                         }
1683*554f68d3SGreg Clayton 
1684*554f68d3SGreg Clayton                         if (get_function_vars)
1685*554f68d3SGreg Clayton                         {
1686*554f68d3SGreg Clayton                             variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true);
1687*554f68d3SGreg Clayton                         }
1688*554f68d3SGreg Clayton 
1689*554f68d3SGreg Clayton                         if (inline_info)
1690*554f68d3SGreg Clayton                         {
1691*554f68d3SGreg Clayton                             s.PutCString (cstr);
1692*554f68d3SGreg Clayton                             s.PutCString (" [inlined] ");
1693*554f68d3SGreg Clayton                             cstr = inline_info->GetName().GetCString();
1694*554f68d3SGreg Clayton                         }
1695*554f68d3SGreg Clayton 
1696*554f68d3SGreg Clayton                         VariableList args;
1697*554f68d3SGreg Clayton                         if (variable_list_sp)
1698*554f68d3SGreg Clayton                             variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args);
1699*554f68d3SGreg Clayton                         if (args.GetSize() > 0)
1700*554f68d3SGreg Clayton                         {
1701*554f68d3SGreg Clayton                             const char *open_paren = strchr (cstr, '(');
1702*554f68d3SGreg Clayton                             const char *close_paren = nullptr;
1703*554f68d3SGreg Clayton                             const char *generic = strchr(cstr, '<');
1704*554f68d3SGreg Clayton                             // if before the arguments list begins there is a template sign
1705*554f68d3SGreg Clayton                             // then scan to the end of the generic args before you try to find
1706*554f68d3SGreg Clayton                             // the arguments list
1707*554f68d3SGreg Clayton                             if (generic && open_paren && generic < open_paren)
1708*554f68d3SGreg Clayton                             {
1709*554f68d3SGreg Clayton                                 int generic_depth = 1;
1710*554f68d3SGreg Clayton                                 ++generic;
1711*554f68d3SGreg Clayton                                 for (;
1712*554f68d3SGreg Clayton                                      *generic && generic_depth > 0;
1713*554f68d3SGreg Clayton                                      generic++)
1714*554f68d3SGreg Clayton                                 {
1715*554f68d3SGreg Clayton                                     if (*generic == '<')
1716*554f68d3SGreg Clayton                                         generic_depth++;
1717*554f68d3SGreg Clayton                                     if (*generic == '>')
1718*554f68d3SGreg Clayton                                         generic_depth--;
1719*554f68d3SGreg Clayton                                 }
1720*554f68d3SGreg Clayton                                 if (*generic)
1721*554f68d3SGreg Clayton                                     open_paren = strchr(generic, '(');
1722*554f68d3SGreg Clayton                                 else
1723*554f68d3SGreg Clayton                                     open_paren = nullptr;
1724*554f68d3SGreg Clayton                             }
1725*554f68d3SGreg Clayton                             if (open_paren)
1726*554f68d3SGreg Clayton                             {
1727*554f68d3SGreg Clayton                                 if (IsToken (open_paren, "(anonymous namespace)"))
1728*554f68d3SGreg Clayton                                 {
1729*554f68d3SGreg Clayton                                     open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '(');
1730*554f68d3SGreg Clayton                                     if (open_paren)
1731*554f68d3SGreg Clayton                                         close_paren = strchr (open_paren, ')');
1732*554f68d3SGreg Clayton                                 }
1733*554f68d3SGreg Clayton                                 else
1734*554f68d3SGreg Clayton                                     close_paren = strchr (open_paren, ')');
1735*554f68d3SGreg Clayton                             }
1736*554f68d3SGreg Clayton 
1737*554f68d3SGreg Clayton                             if (open_paren)
1738*554f68d3SGreg Clayton                                 s.Write(cstr, open_paren - cstr + 1);
1739*554f68d3SGreg Clayton                             else
1740*554f68d3SGreg Clayton                             {
1741*554f68d3SGreg Clayton                                 s.PutCString (cstr);
1742*554f68d3SGreg Clayton                                 s.PutChar ('(');
1743*554f68d3SGreg Clayton                             }
1744*554f68d3SGreg Clayton                             const size_t num_args = args.GetSize();
1745*554f68d3SGreg Clayton                             for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx)
1746*554f68d3SGreg Clayton                             {
1747*554f68d3SGreg Clayton                                 std::string buffer;
1748*554f68d3SGreg Clayton 
1749*554f68d3SGreg Clayton                                 VariableSP var_sp (args.GetVariableAtIndex (arg_idx));
1750*554f68d3SGreg Clayton                                 ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp));
1751*554f68d3SGreg Clayton                                 const char *var_representation = nullptr;
1752*554f68d3SGreg Clayton                                 const char *var_name = var_value_sp->GetName().GetCString();
1753*554f68d3SGreg Clayton                                 if (var_value_sp->GetClangType().IsAggregateType() &&
1754*554f68d3SGreg Clayton                                     DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get()))
1755*554f68d3SGreg Clayton                                 {
1756*554f68d3SGreg Clayton                                     static StringSummaryFormat format(TypeSummaryImpl::Flags()
1757*554f68d3SGreg Clayton                                                                       .SetHideItemNames(false)
1758*554f68d3SGreg Clayton                                                                       .SetShowMembersOneLiner(true),
1759*554f68d3SGreg Clayton                                                                       "");
1760*554f68d3SGreg Clayton                                     format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions());
1761*554f68d3SGreg Clayton                                     var_representation = buffer.c_str();
1762*554f68d3SGreg Clayton                                 }
1763*554f68d3SGreg Clayton                                 else
1764*554f68d3SGreg Clayton                                     var_representation = var_value_sp->GetValueAsCString();
1765*554f68d3SGreg Clayton                                 if (arg_idx > 0)
1766*554f68d3SGreg Clayton                                     s.PutCString (", ");
1767*554f68d3SGreg Clayton                                 if (var_value_sp->GetError().Success())
1768*554f68d3SGreg Clayton                                 {
1769*554f68d3SGreg Clayton                                     if (var_representation)
1770*554f68d3SGreg Clayton                                         s.Printf ("%s=%s", var_name, var_representation);
1771*554f68d3SGreg Clayton                                     else
1772*554f68d3SGreg Clayton                                         s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString());
1773*554f68d3SGreg Clayton                                 }
1774*554f68d3SGreg Clayton                                 else
1775*554f68d3SGreg Clayton                                     s.Printf ("%s=<unavailable>", var_name);
1776*554f68d3SGreg Clayton                             }
1777*554f68d3SGreg Clayton 
1778*554f68d3SGreg Clayton                             if (close_paren)
1779*554f68d3SGreg Clayton                                 s.PutCString (close_paren);
1780*554f68d3SGreg Clayton                             else
1781*554f68d3SGreg Clayton                                 s.PutChar(')');
1782*554f68d3SGreg Clayton 
1783*554f68d3SGreg Clayton                         }
1784*554f68d3SGreg Clayton                         else
1785*554f68d3SGreg Clayton                         {
1786*554f68d3SGreg Clayton                             s.PutCString(cstr);
1787*554f68d3SGreg Clayton                         }
1788*554f68d3SGreg Clayton                         return true;
1789*554f68d3SGreg Clayton                     }
1790*554f68d3SGreg Clayton                 }
1791*554f68d3SGreg Clayton                 else if (sc->symbol)
1792*554f68d3SGreg Clayton                 {
1793*554f68d3SGreg Clayton                     const char *cstr = sc->symbol->GetName().AsCString (NULL);
1794*554f68d3SGreg Clayton                     if (cstr)
1795*554f68d3SGreg Clayton                     {
1796*554f68d3SGreg Clayton                         s.PutCString(cstr);
1797*554f68d3SGreg Clayton                         return true;
1798*554f68d3SGreg Clayton                     }
1799*554f68d3SGreg Clayton                 }
1800*554f68d3SGreg Clayton             }
1801*554f68d3SGreg Clayton             return false;
1802*554f68d3SGreg Clayton 
1803*554f68d3SGreg Clayton         case Entry::Type::FunctionAddrOffset:
1804*554f68d3SGreg Clayton             if (addr)
1805*554f68d3SGreg Clayton             {
1806*554f68d3SGreg Clayton                 if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, *addr, false, false))
1807*554f68d3SGreg Clayton                     return true;
1808*554f68d3SGreg Clayton             }
1809*554f68d3SGreg Clayton             return false;
1810*554f68d3SGreg Clayton 
1811*554f68d3SGreg Clayton         case Entry::Type::FunctionAddrOffsetConcrete:
1812*554f68d3SGreg Clayton             if (addr)
1813*554f68d3SGreg Clayton             {
1814*554f68d3SGreg Clayton                 if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, *addr, true, true))
1815*554f68d3SGreg Clayton                     return true;
1816*554f68d3SGreg Clayton             }
1817*554f68d3SGreg Clayton             return false;
1818*554f68d3SGreg Clayton 
1819*554f68d3SGreg Clayton         case Entry::Type::FunctionLineOffset:
1820*554f68d3SGreg Clayton             if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, sc->line_entry.range.GetBaseAddress(), false, false))
1821*554f68d3SGreg Clayton                 return true;
1822*554f68d3SGreg Clayton             return false;
1823*554f68d3SGreg Clayton 
1824*554f68d3SGreg Clayton         case Entry::Type::FunctionPCOffset:
1825*554f68d3SGreg Clayton             if (exe_ctx)
1826*554f68d3SGreg Clayton             {
1827*554f68d3SGreg Clayton                 StackFrame *frame = exe_ctx->GetFramePtr();
1828*554f68d3SGreg Clayton                 if (frame)
1829*554f68d3SGreg Clayton                 {
1830*554f68d3SGreg Clayton                     if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, frame->GetFrameCodeAddress(), false, false))
1831*554f68d3SGreg Clayton                         return true;
1832*554f68d3SGreg Clayton                 }
1833*554f68d3SGreg Clayton             }
1834*554f68d3SGreg Clayton             return false;
1835*554f68d3SGreg Clayton 
1836*554f68d3SGreg Clayton         case Entry::Type::LineEntryFile:
1837*554f68d3SGreg Clayton             if (sc && sc->line_entry.IsValid())
1838*554f68d3SGreg Clayton             {
1839*554f68d3SGreg Clayton                 Module *module = sc->module_sp.get();
1840*554f68d3SGreg Clayton                 if (module)
1841*554f68d3SGreg Clayton                 {
1842*554f68d3SGreg Clayton                     if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number))
1843*554f68d3SGreg Clayton                         return true;
1844*554f68d3SGreg Clayton                 }
1845*554f68d3SGreg Clayton             }
1846*554f68d3SGreg Clayton             return false;
1847*554f68d3SGreg Clayton 
1848*554f68d3SGreg Clayton         case Entry::Type::LineEntryLineNumber:
1849*554f68d3SGreg Clayton             if (sc && sc->line_entry.IsValid())
1850*554f68d3SGreg Clayton             {
1851*554f68d3SGreg Clayton                 const char *format = "%" PRIu32;
1852*554f68d3SGreg Clayton                 if (!entry.printf_format.empty())
1853*554f68d3SGreg Clayton                     format = entry.printf_format.c_str();
1854*554f68d3SGreg Clayton                 s.Printf(format, sc->line_entry.line);
1855*554f68d3SGreg Clayton                 return true;
1856*554f68d3SGreg Clayton             }
1857*554f68d3SGreg Clayton             return false;
1858*554f68d3SGreg Clayton 
1859*554f68d3SGreg Clayton         case Entry::Type::LineEntryStartAddress:
1860*554f68d3SGreg Clayton         case Entry::Type::LineEntryEndAddress:
1861*554f68d3SGreg Clayton             if (sc && sc->line_entry.range.GetBaseAddress().IsValid())
1862*554f68d3SGreg Clayton             {
1863*554f68d3SGreg Clayton                 Address addr = sc->line_entry.range.GetBaseAddress();
1864*554f68d3SGreg Clayton 
1865*554f68d3SGreg Clayton                 if (entry.type == Entry::Type::LineEntryEndAddress)
1866*554f68d3SGreg Clayton                     addr.Slide(sc->line_entry.range.GetByteSize());
1867*554f68d3SGreg Clayton                 if (DumpAddress(s, sc, exe_ctx, addr, false))
1868*554f68d3SGreg Clayton                     return true;
1869*554f68d3SGreg Clayton             }
1870*554f68d3SGreg Clayton             return false;
1871*554f68d3SGreg Clayton 
1872*554f68d3SGreg Clayton         case Entry::Type::CurrentPCArrow:
1873*554f68d3SGreg Clayton             if (addr && exe_ctx && exe_ctx->GetFramePtr())
1874*554f68d3SGreg Clayton             {
1875*554f68d3SGreg Clayton                 RegisterContextSP reg_ctx = exe_ctx->GetFramePtr()->GetRegisterContextSP();
1876*554f68d3SGreg Clayton                 if (reg_ctx.get())
1877*554f68d3SGreg Clayton                 {
1878*554f68d3SGreg Clayton                     addr_t pc_loadaddr = reg_ctx->GetPC();
1879*554f68d3SGreg Clayton                     if (pc_loadaddr != LLDB_INVALID_ADDRESS)
1880*554f68d3SGreg Clayton                     {
1881*554f68d3SGreg Clayton                         Address pc;
1882*554f68d3SGreg Clayton                         pc.SetLoadAddress (pc_loadaddr, exe_ctx->GetTargetPtr());
1883*554f68d3SGreg Clayton                         if (pc == *addr)
1884*554f68d3SGreg Clayton                         {
1885*554f68d3SGreg Clayton                             s.Printf ("-> ");
1886*554f68d3SGreg Clayton                             return true;
1887*554f68d3SGreg Clayton                         }
1888*554f68d3SGreg Clayton                     }
1889*554f68d3SGreg Clayton                 }
1890*554f68d3SGreg Clayton                 s.Printf("   ");
1891*554f68d3SGreg Clayton                 return true;
1892*554f68d3SGreg Clayton             }
1893*554f68d3SGreg Clayton             return false;
1894*554f68d3SGreg Clayton     }
1895*554f68d3SGreg Clayton     return false;
1896*554f68d3SGreg Clayton }
1897*554f68d3SGreg Clayton 
1898*554f68d3SGreg Clayton static bool
1899*554f68d3SGreg Clayton DumpCommaSeparatedChildEntryNames (Stream &s, const FormatEntity::Entry::Definition *parent)
1900*554f68d3SGreg Clayton {
1901*554f68d3SGreg Clayton     if (parent->children)
1902*554f68d3SGreg Clayton     {
1903*554f68d3SGreg Clayton         const size_t n = parent->num_children;
1904*554f68d3SGreg Clayton         for (size_t i=0; i<n; ++i)
1905*554f68d3SGreg Clayton         {
1906*554f68d3SGreg Clayton             if (i > 0)
1907*554f68d3SGreg Clayton                 s.PutCString(", ");
1908*554f68d3SGreg Clayton             s.Printf ("\"%s\"", parent->children[i].name);
1909*554f68d3SGreg Clayton         }
1910*554f68d3SGreg Clayton         return true;
1911*554f68d3SGreg Clayton     }
1912*554f68d3SGreg Clayton     return false;
1913*554f68d3SGreg Clayton }
1914*554f68d3SGreg Clayton 
1915*554f68d3SGreg Clayton 
1916*554f68d3SGreg Clayton static Error
1917*554f68d3SGreg Clayton ParseEntry (const llvm::StringRef &format_str,
1918*554f68d3SGreg Clayton             const FormatEntity::Entry::Definition *parent,
1919*554f68d3SGreg Clayton             FormatEntity::Entry &entry)
1920*554f68d3SGreg Clayton {
1921*554f68d3SGreg Clayton     Error error;
1922*554f68d3SGreg Clayton 
1923*554f68d3SGreg Clayton     const size_t sep_pos = format_str.find_first_of(".[:");
1924*554f68d3SGreg Clayton     const char sep_char = (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos];
1925*554f68d3SGreg Clayton     llvm::StringRef key = format_str.substr(0, sep_pos);
1926*554f68d3SGreg Clayton 
1927*554f68d3SGreg Clayton     const size_t n = parent->num_children;
1928*554f68d3SGreg Clayton     for (size_t i=0; i<n; ++i)
1929*554f68d3SGreg Clayton     {
1930*554f68d3SGreg Clayton         const FormatEntity::Entry::Definition *entry_def = parent->children + i;
1931*554f68d3SGreg Clayton         if (key.equals(entry_def->name) || entry_def->name[0] == '*')
1932*554f68d3SGreg Clayton         {
1933*554f68d3SGreg Clayton             llvm::StringRef value;
1934*554f68d3SGreg Clayton             if (sep_char)
1935*554f68d3SGreg Clayton                 value = format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1));
1936*554f68d3SGreg Clayton             switch (entry_def->type)
1937*554f68d3SGreg Clayton             {
1938*554f68d3SGreg Clayton                 case FormatEntity::Entry::Type::ParentString:
1939*554f68d3SGreg Clayton                     entry.string = std::move(format_str.str());
1940*554f68d3SGreg Clayton                     return error; // Success
1941*554f68d3SGreg Clayton 
1942*554f68d3SGreg Clayton                 case FormatEntity::Entry::Type::ParentNumber:
1943*554f68d3SGreg Clayton                     entry.number = entry_def->data;
1944*554f68d3SGreg Clayton                     return error; // Success
1945*554f68d3SGreg Clayton 
1946*554f68d3SGreg Clayton                 case FormatEntity::Entry::Type::InsertString:
1947*554f68d3SGreg Clayton                     entry.type = entry_def->type;
1948*554f68d3SGreg Clayton                     entry.string = entry_def->string;
1949*554f68d3SGreg Clayton                     return error; // Success
1950*554f68d3SGreg Clayton 
1951*554f68d3SGreg Clayton                 default:
1952*554f68d3SGreg Clayton                     entry.type = entry_def->type;
1953*554f68d3SGreg Clayton                     break;
1954*554f68d3SGreg Clayton             }
1955*554f68d3SGreg Clayton 
1956*554f68d3SGreg Clayton             if (value.empty())
1957*554f68d3SGreg Clayton             {
1958*554f68d3SGreg Clayton                 if (entry_def->type == FormatEntity::Entry::Type::Invalid)
1959*554f68d3SGreg Clayton                 {
1960*554f68d3SGreg Clayton                     if (entry_def->children)
1961*554f68d3SGreg Clayton                     {
1962*554f68d3SGreg Clayton                         StreamString error_strm;
1963*554f68d3SGreg Clayton                         error_strm.Printf("'%s' can't be specified on its own, you must access one of its children: ", entry_def->name);
1964*554f68d3SGreg Clayton                         DumpCommaSeparatedChildEntryNames (error_strm, entry_def);
1965*554f68d3SGreg Clayton                         error.SetErrorStringWithFormat("%s", error_strm.GetString().c_str());
1966*554f68d3SGreg Clayton                     }
1967*554f68d3SGreg Clayton                     else if (sep_char == ':')
1968*554f68d3SGreg Clayton                     {
1969*554f68d3SGreg Clayton                         // Any value whose separator is a with a ':' means this value has a string argument
1970*554f68d3SGreg Clayton                         // that needs to be stored in the entry (like "${script.var:}").
1971*554f68d3SGreg Clayton                         // In this case the string value is the empty string which is ok.
1972*554f68d3SGreg Clayton                     }
1973*554f68d3SGreg Clayton                     else
1974*554f68d3SGreg Clayton                     {
1975*554f68d3SGreg Clayton                         error.SetErrorStringWithFormat("%s", "invalid entry definitions");
1976*554f68d3SGreg Clayton                     }
1977*554f68d3SGreg Clayton                 }
1978*554f68d3SGreg Clayton             }
1979*554f68d3SGreg Clayton             else
1980*554f68d3SGreg Clayton             {
1981*554f68d3SGreg Clayton                 if (entry_def->children)
1982*554f68d3SGreg Clayton                 {
1983*554f68d3SGreg Clayton                     error = ParseEntry (value, entry_def, entry);
1984*554f68d3SGreg Clayton                 }
1985*554f68d3SGreg Clayton                 else if (sep_char == ':')
1986*554f68d3SGreg Clayton                 {
1987*554f68d3SGreg Clayton                     // Any value whose separator is a with a ':' means this value has a string argument
1988*554f68d3SGreg Clayton                     // that needs to be stored in the entry (like "${script.var:modulename.function}")
1989*554f68d3SGreg Clayton                     entry.string = std::move(value.str());
1990*554f68d3SGreg Clayton                 }
1991*554f68d3SGreg Clayton                 else
1992*554f68d3SGreg Clayton                 {
1993*554f68d3SGreg Clayton                     error.SetErrorStringWithFormat("'%s' followed by '%s' but it has no children",
1994*554f68d3SGreg Clayton                                                    key.str().c_str(),
1995*554f68d3SGreg Clayton                                                    value.str().c_str());
1996*554f68d3SGreg Clayton                 }
1997*554f68d3SGreg Clayton             }
1998*554f68d3SGreg Clayton             return error;
1999*554f68d3SGreg Clayton         }
2000*554f68d3SGreg Clayton     }
2001*554f68d3SGreg Clayton     StreamString error_strm;
2002*554f68d3SGreg Clayton     if (parent->type == FormatEntity::Entry::Type::Root)
2003*554f68d3SGreg Clayton         error_strm.Printf("invalid top level item '%s'. Valid top level items are: ", key.str().c_str());
2004*554f68d3SGreg Clayton     else
2005*554f68d3SGreg Clayton         error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ", key.str().c_str(), parent->name);
2006*554f68d3SGreg Clayton     DumpCommaSeparatedChildEntryNames (error_strm, parent);
2007*554f68d3SGreg Clayton     error.SetErrorStringWithFormat("%s", error_strm.GetString().c_str());
2008*554f68d3SGreg Clayton     return error;
2009*554f68d3SGreg Clayton }
2010*554f68d3SGreg Clayton 
2011*554f68d3SGreg Clayton 
2012*554f68d3SGreg Clayton static const FormatEntity::Entry::Definition *
2013*554f68d3SGreg Clayton FindEntry (const llvm::StringRef &format_str, const FormatEntity::Entry::Definition *parent, llvm::StringRef &remainder)
2014*554f68d3SGreg Clayton {
2015*554f68d3SGreg Clayton     Error error;
2016*554f68d3SGreg Clayton 
2017*554f68d3SGreg Clayton     std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.');
2018*554f68d3SGreg Clayton     const size_t n = parent->num_children;
2019*554f68d3SGreg Clayton     for (size_t i=0; i<n; ++i)
2020*554f68d3SGreg Clayton     {
2021*554f68d3SGreg Clayton         const FormatEntity::Entry::Definition *entry_def = parent->children + i;
2022*554f68d3SGreg Clayton         if (p.first.equals(entry_def->name) || entry_def->name[0] == '*')
2023*554f68d3SGreg Clayton         {
2024*554f68d3SGreg Clayton             if (p.second.empty())
2025*554f68d3SGreg Clayton             {
2026*554f68d3SGreg Clayton                 if (format_str.back() == '.')
2027*554f68d3SGreg Clayton                     remainder = format_str.drop_front(format_str.size() - 1);
2028*554f68d3SGreg Clayton                 else
2029*554f68d3SGreg Clayton                     remainder = llvm::StringRef(); // Exact match
2030*554f68d3SGreg Clayton                 return entry_def;
2031*554f68d3SGreg Clayton             }
2032*554f68d3SGreg Clayton             else
2033*554f68d3SGreg Clayton             {
2034*554f68d3SGreg Clayton                 if (entry_def->children)
2035*554f68d3SGreg Clayton                 {
2036*554f68d3SGreg Clayton                     return FindEntry (p.second, entry_def, remainder);
2037*554f68d3SGreg Clayton                 }
2038*554f68d3SGreg Clayton                 else
2039*554f68d3SGreg Clayton                 {
2040*554f68d3SGreg Clayton                     remainder = p.second;
2041*554f68d3SGreg Clayton                     return entry_def;
2042*554f68d3SGreg Clayton                 }
2043*554f68d3SGreg Clayton             }
2044*554f68d3SGreg Clayton         }
2045*554f68d3SGreg Clayton     }
2046*554f68d3SGreg Clayton     remainder = format_str;
2047*554f68d3SGreg Clayton     return parent;
2048*554f68d3SGreg Clayton }
2049*554f68d3SGreg Clayton 
2050*554f68d3SGreg Clayton Error
2051*554f68d3SGreg Clayton FormatEntity::ParseInternal (llvm::StringRef &format, Entry &parent_entry, uint32_t depth)
2052*554f68d3SGreg Clayton {
2053*554f68d3SGreg Clayton     Error error;
2054*554f68d3SGreg Clayton     while (!format.empty() && error.Success())
2055*554f68d3SGreg Clayton     {
2056*554f68d3SGreg Clayton         const size_t non_special_chars = format.find_first_of("${}\\");
2057*554f68d3SGreg Clayton 
2058*554f68d3SGreg Clayton         if (non_special_chars == llvm::StringRef::npos)
2059*554f68d3SGreg Clayton         {
2060*554f68d3SGreg Clayton             // No special characters, just string bytes so add them and we are done
2061*554f68d3SGreg Clayton             parent_entry.AppendText(format);
2062*554f68d3SGreg Clayton             return error;
2063*554f68d3SGreg Clayton         }
2064*554f68d3SGreg Clayton 
2065*554f68d3SGreg Clayton         if (non_special_chars > 0)
2066*554f68d3SGreg Clayton         {
2067*554f68d3SGreg Clayton             // We have a special character, so add all characters before these as a plain string
2068*554f68d3SGreg Clayton             parent_entry.AppendText(format.substr(0,non_special_chars));
2069*554f68d3SGreg Clayton             format = format.drop_front(non_special_chars);
2070*554f68d3SGreg Clayton         }
2071*554f68d3SGreg Clayton 
2072*554f68d3SGreg Clayton         switch (format[0])
2073*554f68d3SGreg Clayton         {
2074*554f68d3SGreg Clayton             case '\0':
2075*554f68d3SGreg Clayton                 return error;
2076*554f68d3SGreg Clayton 
2077*554f68d3SGreg Clayton             case '{':
2078*554f68d3SGreg Clayton                 {
2079*554f68d3SGreg Clayton                     format = format.drop_front(); // Skip the '{'
2080*554f68d3SGreg Clayton                     Entry scope_entry(Entry::Type::Scope);
2081*554f68d3SGreg Clayton                     error = FormatEntity::ParseInternal (format, scope_entry, depth+1);
2082*554f68d3SGreg Clayton                     if (error.Fail())
2083*554f68d3SGreg Clayton                         return error;
2084*554f68d3SGreg Clayton                     parent_entry.AppendEntry(std::move(scope_entry));
2085*554f68d3SGreg Clayton                 }
2086*554f68d3SGreg Clayton                 break;
2087*554f68d3SGreg Clayton 
2088*554f68d3SGreg Clayton             case '}':
2089*554f68d3SGreg Clayton                 if (depth == 0)
2090*554f68d3SGreg Clayton                     error.SetErrorString("unmatched '}' character");
2091*554f68d3SGreg Clayton                 else
2092*554f68d3SGreg Clayton                     format = format.drop_front(); // Skip the '}' as we are at the end of the scope
2093*554f68d3SGreg Clayton                 return error;
2094*554f68d3SGreg Clayton 
2095*554f68d3SGreg Clayton             case '\\':
2096*554f68d3SGreg Clayton                 {
2097*554f68d3SGreg Clayton                     format = format.drop_front(); // Skip the '\' character
2098*554f68d3SGreg Clayton                     if (format.empty())
2099*554f68d3SGreg Clayton                     {
2100*554f68d3SGreg Clayton                         error.SetErrorString("'\\' character was not followed by another character");
2101*554f68d3SGreg Clayton                         return error;
2102*554f68d3SGreg Clayton                     }
2103*554f68d3SGreg Clayton 
2104*554f68d3SGreg Clayton                     const char desens_char = format[0];
2105*554f68d3SGreg Clayton                     format = format.drop_front(); // Skip the desensitized char character
2106*554f68d3SGreg Clayton                     switch (desens_char)
2107*554f68d3SGreg Clayton                     {
2108*554f68d3SGreg Clayton                         case 'a': parent_entry.AppendChar('\a'); break;
2109*554f68d3SGreg Clayton                         case 'b': parent_entry.AppendChar('\b'); break;
2110*554f68d3SGreg Clayton                         case 'f': parent_entry.AppendChar('\f'); break;
2111*554f68d3SGreg Clayton                         case 'n': parent_entry.AppendChar('\n'); break;
2112*554f68d3SGreg Clayton                         case 'r': parent_entry.AppendChar('\r'); break;
2113*554f68d3SGreg Clayton                         case 't': parent_entry.AppendChar('\t'); break;
2114*554f68d3SGreg Clayton                         case 'v': parent_entry.AppendChar('\v'); break;
2115*554f68d3SGreg Clayton                         case '\'': parent_entry.AppendChar('\''); break;
2116*554f68d3SGreg Clayton                         case '\\': parent_entry.AppendChar('\\'); break;
2117*554f68d3SGreg Clayton                         case '0':
2118*554f68d3SGreg Clayton                             // 1 to 3 octal chars
2119*554f68d3SGreg Clayton                         {
2120*554f68d3SGreg Clayton                             // Make a string that can hold onto the initial zero char,
2121*554f68d3SGreg Clayton                             // up to 3 octal digits, and a terminating NULL.
2122*554f68d3SGreg Clayton                             char oct_str[5] = { 0, 0, 0, 0, 0 };
2123*554f68d3SGreg Clayton 
2124*554f68d3SGreg Clayton                             int i;
2125*554f68d3SGreg Clayton                             for (i=0; (format[i] >= '0' && format[i] <= '7') && i<4; ++i)
2126*554f68d3SGreg Clayton                                 oct_str[i] = format[i];
2127*554f68d3SGreg Clayton 
2128*554f68d3SGreg Clayton                             // We don't want to consume the last octal character since
2129*554f68d3SGreg Clayton                             // the main for loop will do this for us, so we advance p by
2130*554f68d3SGreg Clayton                             // one less than i (even if i is zero)
2131*554f68d3SGreg Clayton                             format = format.drop_front(i);
2132*554f68d3SGreg Clayton                             unsigned long octal_value = ::strtoul (oct_str, NULL, 8);
2133*554f68d3SGreg Clayton                             if (octal_value <= UINT8_MAX)
2134*554f68d3SGreg Clayton                             {
2135*554f68d3SGreg Clayton                                 parent_entry.AppendChar((char)octal_value);
2136*554f68d3SGreg Clayton                             }
2137*554f68d3SGreg Clayton                             else
2138*554f68d3SGreg Clayton                             {
2139*554f68d3SGreg Clayton                                 error.SetErrorString("octal number is larger than a single byte");
2140*554f68d3SGreg Clayton                                 return error;
2141*554f68d3SGreg Clayton                             }
2142*554f68d3SGreg Clayton                         }
2143*554f68d3SGreg Clayton                             break;
2144*554f68d3SGreg Clayton 
2145*554f68d3SGreg Clayton                         case 'x':
2146*554f68d3SGreg Clayton                             // hex number in the format
2147*554f68d3SGreg Clayton                             if (isxdigit(format[0]))
2148*554f68d3SGreg Clayton                             {
2149*554f68d3SGreg Clayton                                 // Make a string that can hold onto two hex chars plus a
2150*554f68d3SGreg Clayton                                 // NULL terminator
2151*554f68d3SGreg Clayton                                 char hex_str[3] = { 0,0,0 };
2152*554f68d3SGreg Clayton                                 hex_str[0] = format[0];
2153*554f68d3SGreg Clayton 
2154*554f68d3SGreg Clayton                                 format = format.drop_front();
2155*554f68d3SGreg Clayton 
2156*554f68d3SGreg Clayton                                 if (isxdigit(format[0]))
2157*554f68d3SGreg Clayton                                 {
2158*554f68d3SGreg Clayton                                     hex_str[1] = format[0];
2159*554f68d3SGreg Clayton                                     format = format.drop_front();
2160*554f68d3SGreg Clayton                                 }
2161*554f68d3SGreg Clayton 
2162*554f68d3SGreg Clayton                                 unsigned long hex_value = strtoul (hex_str, NULL, 16);
2163*554f68d3SGreg Clayton                                 if (hex_value <= UINT8_MAX)
2164*554f68d3SGreg Clayton                                 {
2165*554f68d3SGreg Clayton                                     parent_entry.AppendChar((char)hex_value);
2166*554f68d3SGreg Clayton                                 }
2167*554f68d3SGreg Clayton                                 else
2168*554f68d3SGreg Clayton                                 {
2169*554f68d3SGreg Clayton                                     error.SetErrorString("hex number is larger than a single byte");
2170*554f68d3SGreg Clayton                                     return error;
2171*554f68d3SGreg Clayton                                 }
2172*554f68d3SGreg Clayton                             }
2173*554f68d3SGreg Clayton                             else
2174*554f68d3SGreg Clayton                             {
2175*554f68d3SGreg Clayton                                 parent_entry.AppendChar(desens_char);
2176*554f68d3SGreg Clayton                             }
2177*554f68d3SGreg Clayton                             break;
2178*554f68d3SGreg Clayton 
2179*554f68d3SGreg Clayton                         default:
2180*554f68d3SGreg Clayton                             // Just desensitize any other character by just printing what
2181*554f68d3SGreg Clayton                             // came after the '\'
2182*554f68d3SGreg Clayton                             parent_entry.AppendChar(desens_char);
2183*554f68d3SGreg Clayton                             break;
2184*554f68d3SGreg Clayton                     }
2185*554f68d3SGreg Clayton                 }
2186*554f68d3SGreg Clayton                 break;
2187*554f68d3SGreg Clayton 
2188*554f68d3SGreg Clayton             case '$':
2189*554f68d3SGreg Clayton                 if (format.size() == 1)
2190*554f68d3SGreg Clayton                 {
2191*554f68d3SGreg Clayton                     // '$' at the end of a format string, just print the '$'
2192*554f68d3SGreg Clayton                     parent_entry.AppendText("$");
2193*554f68d3SGreg Clayton                 }
2194*554f68d3SGreg Clayton                 else
2195*554f68d3SGreg Clayton                 {
2196*554f68d3SGreg Clayton                     format = format.drop_front(); // Skip the '$'
2197*554f68d3SGreg Clayton 
2198*554f68d3SGreg Clayton                     if (format[0] == '{')
2199*554f68d3SGreg Clayton                     {
2200*554f68d3SGreg Clayton                         format = format.drop_front(); // Skip the '{'
2201*554f68d3SGreg Clayton 
2202*554f68d3SGreg Clayton                         llvm::StringRef variable, variable_format;
2203*554f68d3SGreg Clayton                         error = FormatEntity::ExtractVariableInfo (format, variable, variable_format);
2204*554f68d3SGreg Clayton                         if (error.Fail())
2205*554f68d3SGreg Clayton                             return error;
2206*554f68d3SGreg Clayton                         bool verify_is_thread_id = false;
2207*554f68d3SGreg Clayton                         Entry entry;
2208*554f68d3SGreg Clayton                         if (!variable_format.empty())
2209*554f68d3SGreg Clayton                         {
2210*554f68d3SGreg Clayton                             entry.printf_format = std::move(variable_format.str());
2211*554f68d3SGreg Clayton 
2212*554f68d3SGreg Clayton                             // If the format contains a '%' we are going to assume this is
2213*554f68d3SGreg Clayton                             // a printf style format. So if you want to format your thread ID
2214*554f68d3SGreg Clayton                             // using "0x%llx" you can use:
2215*554f68d3SGreg Clayton                             // ${thread.id%0x%llx}
2216*554f68d3SGreg Clayton                             //
2217*554f68d3SGreg Clayton                             // If there is no '%' in the format, then it is assumed to be a
2218*554f68d3SGreg Clayton                             // LLDB format name, or one of the extended formats specified in
2219*554f68d3SGreg Clayton                             // the switch statement below.
2220*554f68d3SGreg Clayton 
2221*554f68d3SGreg Clayton                             if (entry.printf_format.find('%') == std::string::npos)
2222*554f68d3SGreg Clayton                             {
2223*554f68d3SGreg Clayton                                 bool clear_printf = false;
2224*554f68d3SGreg Clayton 
2225*554f68d3SGreg Clayton                                 if (FormatManager::GetFormatFromCString(entry.printf_format.c_str(),
2226*554f68d3SGreg Clayton                                                                         false,
2227*554f68d3SGreg Clayton                                                                         entry.fmt))
2228*554f68d3SGreg Clayton                                 {
2229*554f68d3SGreg Clayton                                     // We have an LLDB format, so clear the printf format
2230*554f68d3SGreg Clayton                                     clear_printf = true;
2231*554f68d3SGreg Clayton                                 }
2232*554f68d3SGreg Clayton                                 else if (entry.printf_format.size() == 1)
2233*554f68d3SGreg Clayton                                 {
2234*554f68d3SGreg Clayton                                     switch (entry.printf_format[0])
2235*554f68d3SGreg Clayton                                     {
2236*554f68d3SGreg Clayton                                         case '@':             // if this is an @ sign, print ObjC description
2237*554f68d3SGreg Clayton                                             entry.number = ValueObject::eValueObjectRepresentationStyleLanguageSpecific;
2238*554f68d3SGreg Clayton                                             clear_printf = true;
2239*554f68d3SGreg Clayton                                             break;
2240*554f68d3SGreg Clayton                                         case 'V': // if this is a V, print the value using the default format
2241*554f68d3SGreg Clayton                                             entry.number = ValueObject::eValueObjectRepresentationStyleValue;
2242*554f68d3SGreg Clayton                                             clear_printf = true;
2243*554f68d3SGreg Clayton                                             break;
2244*554f68d3SGreg Clayton                                         case 'L': // if this is an L, print the location of the value
2245*554f68d3SGreg Clayton                                             entry.number = ValueObject::eValueObjectRepresentationStyleLocation;
2246*554f68d3SGreg Clayton                                             clear_printf = true;
2247*554f68d3SGreg Clayton                                             break;
2248*554f68d3SGreg Clayton                                         case 'S': // if this is an S, print the summary after all
2249*554f68d3SGreg Clayton                                             entry.number = ValueObject::eValueObjectRepresentationStyleSummary;
2250*554f68d3SGreg Clayton                                             clear_printf = true;
2251*554f68d3SGreg Clayton                                             break;
2252*554f68d3SGreg Clayton                                         case '#': // if this is a '#', print the number of children
2253*554f68d3SGreg Clayton                                             entry.number = ValueObject::eValueObjectRepresentationStyleChildrenCount;
2254*554f68d3SGreg Clayton                                             clear_printf = true;
2255*554f68d3SGreg Clayton                                             break;
2256*554f68d3SGreg Clayton                                         case 'T': // if this is a 'T', print the type
2257*554f68d3SGreg Clayton                                             entry.number = ValueObject::eValueObjectRepresentationStyleType;
2258*554f68d3SGreg Clayton                                             clear_printf = true;
2259*554f68d3SGreg Clayton                                             break;
2260*554f68d3SGreg Clayton                                         case 'N': // if this is a 'N', print the name
2261*554f68d3SGreg Clayton                                             entry.number = ValueObject::eValueObjectRepresentationStyleName;
2262*554f68d3SGreg Clayton                                             clear_printf = true;
2263*554f68d3SGreg Clayton                                             break;
2264*554f68d3SGreg Clayton                                         case '>': // if this is a '>', print the name
2265*554f68d3SGreg Clayton                                             entry.number = ValueObject::eValueObjectRepresentationStyleExpressionPath;
2266*554f68d3SGreg Clayton                                             clear_printf = true;
2267*554f68d3SGreg Clayton                                             break;
2268*554f68d3SGreg Clayton                                         default:
2269*554f68d3SGreg Clayton                                             error.SetErrorStringWithFormat("invalid format: '%s'", entry.printf_format.c_str());
2270*554f68d3SGreg Clayton                                             return error;
2271*554f68d3SGreg Clayton                                     }
2272*554f68d3SGreg Clayton                                 }
2273*554f68d3SGreg Clayton                                 else if (FormatManager::GetFormatFromCString(entry.printf_format.c_str(),
2274*554f68d3SGreg Clayton                                                                              true,
2275*554f68d3SGreg Clayton                                                                              entry.fmt))
2276*554f68d3SGreg Clayton                                 {
2277*554f68d3SGreg Clayton                                     clear_printf = true;
2278*554f68d3SGreg Clayton                                 }
2279*554f68d3SGreg Clayton                                 else if (entry.printf_format == "tid")
2280*554f68d3SGreg Clayton                                 {
2281*554f68d3SGreg Clayton                                     verify_is_thread_id = true;
2282*554f68d3SGreg Clayton                                 }
2283*554f68d3SGreg Clayton                                 else
2284*554f68d3SGreg Clayton                                 {
2285*554f68d3SGreg Clayton                                     error.SetErrorStringWithFormat("invalid format: '%s'", entry.printf_format.c_str());
2286*554f68d3SGreg Clayton                                     return error;
2287*554f68d3SGreg Clayton                                 }
2288*554f68d3SGreg Clayton 
2289*554f68d3SGreg Clayton                                 // Our format string turned out to not be a printf style format
2290*554f68d3SGreg Clayton                                 // so lets clear the string
2291*554f68d3SGreg Clayton                                 if (clear_printf)
2292*554f68d3SGreg Clayton                                     entry.printf_format.clear();
2293*554f68d3SGreg Clayton                             }
2294*554f68d3SGreg Clayton                         }
2295*554f68d3SGreg Clayton 
2296*554f68d3SGreg Clayton                         // Check for dereferences
2297*554f68d3SGreg Clayton                         if (variable[0] == '*')
2298*554f68d3SGreg Clayton                         {
2299*554f68d3SGreg Clayton                             entry.deref = true;
2300*554f68d3SGreg Clayton                             variable = variable.drop_front();
2301*554f68d3SGreg Clayton                         }
2302*554f68d3SGreg Clayton 
2303*554f68d3SGreg Clayton                         error = ParseEntry (variable, &g_root, entry);
2304*554f68d3SGreg Clayton                         if (error.Fail())
2305*554f68d3SGreg Clayton                             return error;
2306*554f68d3SGreg Clayton 
2307*554f68d3SGreg Clayton                         if (verify_is_thread_id)
2308*554f68d3SGreg Clayton                         {
2309*554f68d3SGreg Clayton                             if (entry.type != Entry::Type::ThreadID &&
2310*554f68d3SGreg Clayton                                 entry.type != Entry::Type::ThreadProtocolID)
2311*554f68d3SGreg Clayton                             {
2312*554f68d3SGreg Clayton                                 error.SetErrorString("the 'tid' format can only be used on ${thread.id} and ${thread.protocol_id}");
2313*554f68d3SGreg Clayton                             }
2314*554f68d3SGreg Clayton                         }
2315*554f68d3SGreg Clayton 
2316*554f68d3SGreg Clayton                         switch (entry.type)
2317*554f68d3SGreg Clayton                         {
2318*554f68d3SGreg Clayton                             case Entry::Type::Variable:
2319*554f68d3SGreg Clayton                             case Entry::Type::VariableSynthetic:
2320*554f68d3SGreg Clayton                                 if (entry.number == 0)
2321*554f68d3SGreg Clayton                                 {
2322*554f68d3SGreg Clayton                                     if (entry.string.empty())
2323*554f68d3SGreg Clayton                                         entry.number = ValueObject::eValueObjectRepresentationStyleValue;
2324*554f68d3SGreg Clayton                                     else
2325*554f68d3SGreg Clayton                                         entry.number = ValueObject::eValueObjectRepresentationStyleSummary;
2326*554f68d3SGreg Clayton                                 }
2327*554f68d3SGreg Clayton                                 break;
2328*554f68d3SGreg Clayton                             default:
2329*554f68d3SGreg Clayton                                 // Make sure someone didn't try to dereference anything but ${var} or ${svar}
2330*554f68d3SGreg Clayton                                 if (entry.deref)
2331*554f68d3SGreg Clayton                                 {
2332*554f68d3SGreg Clayton                                     error.SetErrorStringWithFormat("${%s} can't be dereferenced, only ${var} and ${svar} can.", variable.str().c_str());
2333*554f68d3SGreg Clayton                                     return error;
2334*554f68d3SGreg Clayton                                 }
2335*554f68d3SGreg Clayton                         }
2336*554f68d3SGreg Clayton                         // Check if this entry just wants to insert a constant string
2337*554f68d3SGreg Clayton                         // value into the parent_entry, if so, insert the string with
2338*554f68d3SGreg Clayton                         // AppendText, else append the entry to the parent_entry.
2339*554f68d3SGreg Clayton                         if (entry.type == Entry::Type::InsertString)
2340*554f68d3SGreg Clayton                             parent_entry.AppendText(entry.string.c_str());
2341*554f68d3SGreg Clayton                         else
2342*554f68d3SGreg Clayton                             parent_entry.AppendEntry(std::move(entry));
2343*554f68d3SGreg Clayton                     }
2344*554f68d3SGreg Clayton                 }
2345*554f68d3SGreg Clayton                 break;
2346*554f68d3SGreg Clayton         }
2347*554f68d3SGreg Clayton     }
2348*554f68d3SGreg Clayton     return error;
2349*554f68d3SGreg Clayton }
2350*554f68d3SGreg Clayton 
2351*554f68d3SGreg Clayton 
2352*554f68d3SGreg Clayton Error
2353*554f68d3SGreg Clayton FormatEntity::ExtractVariableInfo (llvm::StringRef &format_str, llvm::StringRef &variable_name, llvm::StringRef &variable_format)
2354*554f68d3SGreg Clayton {
2355*554f68d3SGreg Clayton     Error error;
2356*554f68d3SGreg Clayton     variable_name = llvm::StringRef();
2357*554f68d3SGreg Clayton     variable_format = llvm::StringRef();
2358*554f68d3SGreg Clayton 
2359*554f68d3SGreg Clayton     const size_t paren_pos = format_str.find_first_of('}');
2360*554f68d3SGreg Clayton     if (paren_pos != llvm::StringRef::npos)
2361*554f68d3SGreg Clayton     {
2362*554f68d3SGreg Clayton         const size_t percent_pos = format_str.find_first_of('%');
2363*554f68d3SGreg Clayton         if (percent_pos < paren_pos)
2364*554f68d3SGreg Clayton         {
2365*554f68d3SGreg Clayton             if (percent_pos > 0)
2366*554f68d3SGreg Clayton             {
2367*554f68d3SGreg Clayton                 if (percent_pos > 1)
2368*554f68d3SGreg Clayton                     variable_name = format_str.substr(0, percent_pos);
2369*554f68d3SGreg Clayton                 variable_format = format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1));
2370*554f68d3SGreg Clayton             }
2371*554f68d3SGreg Clayton         }
2372*554f68d3SGreg Clayton         else
2373*554f68d3SGreg Clayton         {
2374*554f68d3SGreg Clayton             variable_name = format_str.substr(0, paren_pos);
2375*554f68d3SGreg Clayton         }
2376*554f68d3SGreg Clayton         // Strip off elements and the formatting and the trailing '}'
2377*554f68d3SGreg Clayton         format_str = format_str.substr(paren_pos + 1);
2378*554f68d3SGreg Clayton     }
2379*554f68d3SGreg Clayton     else
2380*554f68d3SGreg Clayton     {
2381*554f68d3SGreg Clayton         error.SetErrorStringWithFormat("missing terminating '}' character for '${%s'", format_str.str().c_str());
2382*554f68d3SGreg Clayton     }
2383*554f68d3SGreg Clayton     return error;
2384*554f68d3SGreg Clayton }
2385*554f68d3SGreg Clayton 
2386*554f68d3SGreg Clayton bool
2387*554f68d3SGreg Clayton FormatEntity::FormatFileSpec (const FileSpec &file_spec, Stream &s, llvm::StringRef variable_name, llvm::StringRef variable_format)
2388*554f68d3SGreg Clayton {
2389*554f68d3SGreg Clayton     if (variable_name.empty() || variable_name.equals(".fullpath"))
2390*554f68d3SGreg Clayton     {
2391*554f68d3SGreg Clayton         file_spec.Dump(&s);
2392*554f68d3SGreg Clayton         return true;
2393*554f68d3SGreg Clayton     }
2394*554f68d3SGreg Clayton     else if (variable_name.equals(".basename"))
2395*554f68d3SGreg Clayton     {
2396*554f68d3SGreg Clayton         s.PutCString(file_spec.GetFilename().AsCString(""));
2397*554f68d3SGreg Clayton         return true;
2398*554f68d3SGreg Clayton     }
2399*554f68d3SGreg Clayton     else if (variable_name.equals(".dirname"))
2400*554f68d3SGreg Clayton     {
2401*554f68d3SGreg Clayton         s.PutCString(file_spec.GetFilename().AsCString(""));
2402*554f68d3SGreg Clayton         return true;
2403*554f68d3SGreg Clayton     }
2404*554f68d3SGreg Clayton     return false;
2405*554f68d3SGreg Clayton }
2406*554f68d3SGreg Clayton 
2407*554f68d3SGreg Clayton static std::string
2408*554f68d3SGreg Clayton MakeMatch (const llvm::StringRef &prefix, const char *suffix)
2409*554f68d3SGreg Clayton {
2410*554f68d3SGreg Clayton     std::string match(prefix.str());
2411*554f68d3SGreg Clayton     match.append(suffix);
2412*554f68d3SGreg Clayton     return std::move(match);
2413*554f68d3SGreg Clayton }
2414*554f68d3SGreg Clayton 
2415*554f68d3SGreg Clayton static void
2416*554f68d3SGreg Clayton AddMatches (const FormatEntity::Entry::Definition *def,
2417*554f68d3SGreg Clayton             const llvm::StringRef &prefix,
2418*554f68d3SGreg Clayton             const llvm::StringRef &match_prefix,
2419*554f68d3SGreg Clayton             StringList &matches)
2420*554f68d3SGreg Clayton {
2421*554f68d3SGreg Clayton     const size_t n = def->num_children;
2422*554f68d3SGreg Clayton     if (n > 0)
2423*554f68d3SGreg Clayton     {
2424*554f68d3SGreg Clayton         for (size_t i=0; i<n; ++i)
2425*554f68d3SGreg Clayton         {
2426*554f68d3SGreg Clayton             std::string match = std::move(prefix.str());
2427*554f68d3SGreg Clayton             if (match_prefix.empty())
2428*554f68d3SGreg Clayton                 matches.AppendString(MakeMatch (prefix, def->children[i].name));
2429*554f68d3SGreg Clayton             else if (strncmp(def->children[i].name, match_prefix.data(), match_prefix.size()) == 0)
2430*554f68d3SGreg Clayton                 matches.AppendString(MakeMatch (prefix, def->children[i].name + match_prefix.size()));
2431*554f68d3SGreg Clayton         }
2432*554f68d3SGreg Clayton     }
2433*554f68d3SGreg Clayton }
2434*554f68d3SGreg Clayton size_t
2435*554f68d3SGreg Clayton FormatEntity::AutoComplete (const char *s,
2436*554f68d3SGreg Clayton                             int match_start_point,
2437*554f68d3SGreg Clayton                             int max_return_elements,
2438*554f68d3SGreg Clayton                             bool &word_complete,
2439*554f68d3SGreg Clayton                             StringList &matches)
2440*554f68d3SGreg Clayton {
2441*554f68d3SGreg Clayton     word_complete = false;
2442*554f68d3SGreg Clayton     llvm::StringRef str(s + match_start_point);
2443*554f68d3SGreg Clayton     matches.Clear();
2444*554f68d3SGreg Clayton 
2445*554f68d3SGreg Clayton     const size_t dollar_pos = str.rfind('$');
2446*554f68d3SGreg Clayton     if (dollar_pos != llvm::StringRef::npos)
2447*554f68d3SGreg Clayton     {
2448*554f68d3SGreg Clayton         // Hitting TAB after $ at the end of the string add a "{"
2449*554f68d3SGreg Clayton         if (dollar_pos == str.size() - 1)
2450*554f68d3SGreg Clayton         {
2451*554f68d3SGreg Clayton             std::string match = std::move(str.str());
2452*554f68d3SGreg Clayton             match.append("{");
2453*554f68d3SGreg Clayton             matches.AppendString(std::move(match));
2454*554f68d3SGreg Clayton         }
2455*554f68d3SGreg Clayton         else if (str[dollar_pos + 1] == '{')
2456*554f68d3SGreg Clayton         {
2457*554f68d3SGreg Clayton             const size_t close_pos = str.find('}', dollar_pos + 2);
2458*554f68d3SGreg Clayton             if (close_pos == llvm::StringRef::npos)
2459*554f68d3SGreg Clayton             {
2460*554f68d3SGreg Clayton                 const size_t format_pos = str.find('%', dollar_pos + 2);
2461*554f68d3SGreg Clayton                 if (format_pos == llvm::StringRef::npos)
2462*554f68d3SGreg Clayton                 {
2463*554f68d3SGreg Clayton                     llvm::StringRef partial_variable (str.substr(dollar_pos + 2));
2464*554f68d3SGreg Clayton                     if (partial_variable.empty())
2465*554f68d3SGreg Clayton                     {
2466*554f68d3SGreg Clayton                         // Suggest all top level entites as we are just past "${"
2467*554f68d3SGreg Clayton                         AddMatches(&g_root, str, llvm::StringRef(), matches);
2468*554f68d3SGreg Clayton                     }
2469*554f68d3SGreg Clayton                     else
2470*554f68d3SGreg Clayton                     {
2471*554f68d3SGreg Clayton                         // We have a partially specified variable, find it
2472*554f68d3SGreg Clayton                         llvm::StringRef remainder;
2473*554f68d3SGreg Clayton                         const FormatEntity::Entry::Definition* entry_def = FindEntry (partial_variable, &g_root, remainder);
2474*554f68d3SGreg Clayton                         if (entry_def)
2475*554f68d3SGreg Clayton                         {
2476*554f68d3SGreg Clayton                             const size_t n = entry_def->num_children;
2477*554f68d3SGreg Clayton 
2478*554f68d3SGreg Clayton                             if (remainder.empty())
2479*554f68d3SGreg Clayton                             {
2480*554f68d3SGreg Clayton                                 // Exact match
2481*554f68d3SGreg Clayton                                 if (n > 0)
2482*554f68d3SGreg Clayton                                 {
2483*554f68d3SGreg Clayton                                     // "${thread.info" <TAB>
2484*554f68d3SGreg Clayton                                     matches.AppendString(std::move(MakeMatch (str, ".")));
2485*554f68d3SGreg Clayton                                 }
2486*554f68d3SGreg Clayton                                 else
2487*554f68d3SGreg Clayton                                 {
2488*554f68d3SGreg Clayton                                     // "${thread.id" <TAB>
2489*554f68d3SGreg Clayton                                     matches.AppendString(std::move(MakeMatch (str, "}")));
2490*554f68d3SGreg Clayton                                     word_complete = true;
2491*554f68d3SGreg Clayton                                 }
2492*554f68d3SGreg Clayton                             }
2493*554f68d3SGreg Clayton                             else if (remainder.equals("."))
2494*554f68d3SGreg Clayton                             {
2495*554f68d3SGreg Clayton                                 // "${thread." <TAB>
2496*554f68d3SGreg Clayton                                 AddMatches(entry_def, str, llvm::StringRef(), matches);
2497*554f68d3SGreg Clayton                             }
2498*554f68d3SGreg Clayton                             else
2499*554f68d3SGreg Clayton                             {
2500*554f68d3SGreg Clayton                                 // We have a partial match
2501*554f68d3SGreg Clayton                                 // "${thre" <TAB>
2502*554f68d3SGreg Clayton                                 AddMatches(entry_def, str, remainder, matches);
2503*554f68d3SGreg Clayton                             }
2504*554f68d3SGreg Clayton                         }
2505*554f68d3SGreg Clayton                     }
2506*554f68d3SGreg Clayton                 }
2507*554f68d3SGreg Clayton             }
2508*554f68d3SGreg Clayton         }
2509*554f68d3SGreg Clayton     }
2510*554f68d3SGreg Clayton     return matches.GetSize();
2511*554f68d3SGreg Clayton }
2512