1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
31 **************************************************************************/
33 #ifndef SYMBOLGROUPNODE_H
34 #define SYMBOLGROUPNODE_H
43 enum { symbolGroupDebug = 0 };
45 std::ostream &operator<<(std::ostream &, const DEBUG_SYMBOL_PARAMETERS&p);
47 class SymbolGroupNodeVisitor;
49 struct SymbolGroupValueContext;
50 class SymbolGroupNode;
54 typedef std::map<std::string, int> FormatMap; // type or iname to format
57 DumpHumanReadable = 0x1,
58 DumpComplexDumpers = 0x2
62 bool humanReadable() const { return dumpFlags & DumpHumanReadable; }
63 // Helper to decode format option arguments.
64 static FormatMap decodeFormatArgument(const std::string &f);
66 bool recode(const std::string &type, const std::string &iname,
67 const SymbolGroupValueContext &ctx,
68 std::wstring *value, int *encoding) const;
69 int format(const std::string &type, const std::string &iname) const;
72 FormatMap typeFormats;
73 FormatMap individualFormats;
76 std::ostream &operator<<(std::ostream &os, const DumpParameters &);
78 class AbstractSymbolGroupNode
80 AbstractSymbolGroupNode(const AbstractSymbolGroupNode&);
81 AbstractSymbolGroupNode& operator=(const AbstractSymbolGroupNode&);
84 typedef std::vector<AbstractSymbolGroupNode *> AbstractSymbolGroupNodePtrVector;
85 typedef AbstractSymbolGroupNodePtrVector::iterator AbstractSymbolGroupNodePtrVectorIterator;
86 typedef AbstractSymbolGroupNodePtrVector::const_iterator AbstractSymbolGroupNodePtrVectorConstIterator;
88 virtual ~AbstractSymbolGroupNode();
90 // Name to appear in watchwindow
91 const std::string &name() const { return m_name; }
92 // 'iname' used as an internal id.
93 const std::string &iName() const { return m_iname; }
94 // Full iname 'local.x.foo': WARNING: this returns the absolute path not
95 // taking reference nodes into account by recursing up the parents.
96 std::string absoluteFullIName() const;
98 virtual const AbstractSymbolGroupNodePtrVector &children() const = 0;
99 AbstractSymbolGroupNode *childAt(unsigned) const;
101 unsigned indexByIName(const char *) const; // (unsigned(-1) on failure
102 AbstractSymbolGroupNode *childByIName(const char *) const;
103 unsigned indexOf(const AbstractSymbolGroupNode *) const;
105 const AbstractSymbolGroupNode *parent() const { return m_parent; }
106 AbstractSymbolGroupNode *parent() { return m_parent; }
108 unsigned flags() const { return m_flags; }
109 bool testFlags(unsigned f) const { return (m_flags & f) != 0; }
110 void addFlags(unsigned f) { m_flags |= f; }
111 void clearFlags(unsigned f) { m_flags &= ~f; }
113 virtual SymbolGroupNode *asSymbolGroupNode() { return 0; }
114 virtual const SymbolGroupNode *asSymbolGroupNode() const { return 0; }
115 virtual const AbstractSymbolGroupNode *resolveReference() const { return this; }
116 virtual AbstractSymbolGroupNode *resolveReference() { return this; }
118 bool accept(SymbolGroupNodeVisitor &visitor,
119 const std::string &visitingParentIname,
120 unsigned child, unsigned depth);
122 // I/O: GDBMI dump for Visitors, return child count
123 virtual int dump(std::ostream &str, const std::string &visitingFullIname,
124 const DumpParameters &p, const SymbolGroupValueContext &ctx) = 0;
125 // I/O: debug output for Visitors
126 virtual void debug(std::ostream &os, const std::string &visitingFullIname,
127 unsigned verbosity, unsigned depth) const;
129 // For BaseSymbolGroupNode only.
130 void setParent(AbstractSymbolGroupNode *n);
133 explicit AbstractSymbolGroupNode(const std::string &name, const std::string &iname);
135 // Basic GDBMI dumping
136 static inline void dumpBasicData(std::ostream &str, const std::string &aName,
137 const std::string &aFullIname,
138 const std::string &type = std::string(),
139 const std::string &expression = std::string());
142 const std::string m_name;
143 const std::string m_iname;
144 AbstractSymbolGroupNode *m_parent;
148 class BaseSymbolGroupNode : public AbstractSymbolGroupNode
151 virtual const AbstractSymbolGroupNodePtrVector &children() const { return m_children; }
152 void addChild(AbstractSymbolGroupNode *c); // for watches
153 void removeChildAt(unsigned);
156 explicit BaseSymbolGroupNode(const std::string &name, const std::string &iname);
157 virtual ~BaseSymbolGroupNode();
159 void reserveChildren(AbstractSymbolGroupNodePtrVector::size_type s) { m_children.reserve(s); }
162 AbstractSymbolGroupNodePtrVector m_children;
163 void removeChildren();
166 // Dummy fake node to satisfy the watch model for failed additions. Reports error.
167 class ErrorSymbolGroupNode : public BaseSymbolGroupNode
170 explicit ErrorSymbolGroupNode(const std::string &name, const std::string &iname);
172 virtual int dump(std::ostream &str, const std::string &fullIname,
173 const DumpParameters &p, const SymbolGroupValueContext &ctx);
174 virtual void debug(std::ostream &os, const std::string &visitingFullIname,
175 unsigned verbosity, unsigned depth) const;
178 class SymbolGroupNode : public BaseSymbolGroupNode
180 explicit SymbolGroupNode(SymbolGroup *symbolGroup,
182 const std::string &module,
183 const std::string &name,
184 const std::string &iname);
190 SimpleDumperNotApplicable = 0x2, // No dumper available for type
191 SimpleDumperOk = 0x4, // Internal dumper ran, value set
192 SimpleDumperFailed = 0x8, // Internal dumper failed
193 SimpleDumperMask = SimpleDumperNotApplicable|SimpleDumperOk|SimpleDumperFailed,
194 ExpandedByDumper = 0x10,
195 AdditionalSymbol = 0x20, // Introduced by addSymbol, should not be visible
196 Obscured = 0x40, // Symbol is obscured by (for example) fake container children
197 ComplexDumperOk = 0x80,
201 typedef std::vector<DEBUG_SYMBOL_PARAMETERS> SymbolParameterVector;
203 void parseParameters(SymbolParameterVector::size_type index,
204 SymbolParameterVector::size_type parameterOffset,
205 const SymbolParameterVector &vec);
207 static SymbolGroupNode *create(SymbolGroup *sg, const std::string &module, const std::string &name, const SymbolParameterVector &vec);
208 // For root nodes, only: Add a new symbol by name
209 SymbolGroupNode *addSymbolByName(const std::string &module,
210 const std::string &name, // Expression like 'myarray[1]'
211 const std::string &displayName, // Name to be displayed, defaults to name
212 const std::string &iname, // Desired iname, defaults to name
213 std::string *errorMessage);
215 SymbolGroup *symbolGroup() const { return m_symbolGroup; }
217 // I/O: Gdbmi dump for Visitors
218 virtual int dump(std::ostream &str, const std::string &fullIname,
219 const DumpParameters &p, const SymbolGroupValueContext &ctx);
220 // Dumper functionality for reference nodes, returns child count guess
221 int dumpNode(std::ostream &str, const std::string &aName, const std::string &aFullIName,
222 const DumpParameters &p, const SymbolGroupValueContext &ctx);
224 // I/O: debug for Visitors
225 virtual void debug(std::ostream &os, const std::string &visitingFullIname,
226 unsigned verbosity, unsigned depth) const;
228 std::wstring symbolGroupRawValue() const;
229 std::wstring symbolGroupFixedValue() const;
230 // A quick check if symbol is valid by checking for inaccessible value
231 bool isMemoryAccessible() const;
233 std::string type() const;
234 int dumperType() const { return m_dumperType; } // Valid after dumper run
235 int dumperContainerSize() { return m_dumperContainerSize; } // Valid after dumper run
236 unsigned size() const; // Size of value
237 ULONG64 address() const;
238 std::string module() const { return m_module; }
240 bool expand(std::string *errorMessage);
241 bool expandRunComplexDumpers(const SymbolGroupValueContext &ctx, std::string *errorMessage);
242 bool isExpanded() const { return !children().empty(); }
243 bool canExpand() const { return m_parameters.SubElements > 0; }
244 void runComplexDumpers(const SymbolGroupValueContext &ctx);
245 // Cast to a different type. Works only on unexpanded nodes
246 bool typeCast(const std::string &desiredType, std::string *errorMessage);
248 ULONG subElements() const { return m_parameters.SubElements; }
249 ULONG index() const { return m_index; }
251 virtual SymbolGroupNode *asSymbolGroupNode() { return this; }
252 virtual const SymbolGroupNode *asSymbolGroupNode() const { return this; }
254 // Remove self off parent and return the indexes to be shifted or unsigned(-1).
255 bool removeSelf(SymbolGroupNode *root, std::string *errorMessage);
258 const SymbolGroupNode *symbolGroupNodeParent() const;
259 SymbolGroupNode *symbolGroupNodeParent();
260 bool isArrayElement() const;
261 // Notify about expansion/collapsing of a node, shift indexes
262 bool notifyIndexesMoved(ULONG index, bool inserted, ULONG offset);
263 bool runSimpleDumpers(const SymbolGroupValueContext &ctx);
264 std::wstring simpleDumpValue(const SymbolGroupValueContext &ctx);
265 ULONG nextSymbolIndex() const;
267 SymbolGroup *const m_symbolGroup;
268 const std::string m_module;
270 DEBUG_SYMBOL_PARAMETERS m_parameters; // Careful when using ParentSymbol. It might not be correct.
271 std::wstring m_dumperValue;
273 int m_dumperContainerSize;
274 void *m_dumperSpecialInfo; // Opaque information passed from simple to complex dumpers
277 class ReferenceSymbolGroupNode : public AbstractSymbolGroupNode
280 explicit ReferenceSymbolGroupNode(const std::string &name,
281 const std::string &iname,
282 SymbolGroupNode *referencedNode);
283 // Convenience to create a node name name='[1]', iname='1' for arrays
284 static ReferenceSymbolGroupNode *createArrayNode(int index,
285 SymbolGroupNode *referencedNode);
287 virtual int dump(std::ostream &str, const std::string &visitingFullIname,
288 const DumpParameters &p, const SymbolGroupValueContext &ctx);
289 virtual void debug(std::ostream &os, const std::string &visitingFullIname,
290 unsigned verbosity, unsigned depth) const;
292 virtual const AbstractSymbolGroupNodePtrVector &children() const { return m_referencedNode->children(); }
294 virtual const AbstractSymbolGroupNode *resolveReference() const { return m_referencedNode; }
295 virtual AbstractSymbolGroupNode *resolveReference() { return m_referencedNode; }
298 SymbolGroupNode * const m_referencedNode;
301 class MapNodeSymbolGroupNode : public BaseSymbolGroupNode
304 explicit MapNodeSymbolGroupNode(const std::string &name,
305 const std::string &iname,
306 ULONG64 address /* = 0 */,
307 const std::string &type,
308 AbstractSymbolGroupNode *key,
309 AbstractSymbolGroupNode *value);
312 static MapNodeSymbolGroupNode *
313 create(int i, ULONG64 address /* = 0 */, const std::string &type,
314 SymbolGroupNode *key, SymbolGroupNode *value);
316 virtual int dump(std::ostream &str, const std::string &visitingFullIname,
317 const DumpParameters &p, const SymbolGroupValueContext &ctx);
318 virtual void debug(std::ostream &os, const std::string &visitingFullIname,
319 unsigned verbosity, unsigned depth) const;
322 const ULONG64 m_address;
323 const std::string m_type;
326 class SymbolGroupNodeVisitor {
327 SymbolGroupNodeVisitor(const SymbolGroupNodeVisitor&);
328 SymbolGroupNodeVisitor& operator=(const SymbolGroupNodeVisitor&);
330 friend class AbstractSymbolGroupNode;
332 SymbolGroupNodeVisitor() {}
334 virtual ~SymbolGroupNodeVisitor() {}
336 // "local.vi" -> "local"
337 static std::string parentIname(const std::string &iname);
338 static const char iNamePathSeparator = '.';
349 virtual VisitResult visit(AbstractSymbolGroupNode *node,
350 const std::string &fullIname,
351 unsigned child, unsigned depth) = 0;
352 // Helper for formatting output.
353 virtual void childrenVisited(const AbstractSymbolGroupNode * /* node */, unsigned /* depth */) {}
356 class DebugSymbolGroupNodeVisitor : public SymbolGroupNodeVisitor {
358 explicit DebugSymbolGroupNodeVisitor(std::ostream &os, unsigned verbosity = 0);
361 virtual VisitResult visit(AbstractSymbolGroupNode *node,
362 const std::string &fullIname,
363 unsigned child, unsigned depth);
367 const unsigned m_verbosity;
370 class DebugFilterSymbolGroupNodeVisitor : public DebugSymbolGroupNodeVisitor {
372 explicit DebugFilterSymbolGroupNodeVisitor(std::ostream &os,
373 const std::string &filter,
374 const unsigned verbosity = 0);
377 virtual VisitResult visit(AbstractSymbolGroupNode *node,
378 const std::string &fullIname,
379 unsigned child, unsigned depth);
382 const std::string m_filter;
385 class DumpSymbolGroupNodeVisitor : public SymbolGroupNodeVisitor {
387 explicit DumpSymbolGroupNodeVisitor(std::ostream &os,
388 const SymbolGroupValueContext &context,
389 const DumpParameters ¶meters = DumpParameters());
392 virtual VisitResult visit(AbstractSymbolGroupNode *node,
393 const std::string &fullIname,
394 unsigned child, unsigned depth);
395 virtual void childrenVisited(const AbstractSymbolGroupNode * node, unsigned depth);
399 const SymbolGroupValueContext &m_context;
400 const DumpParameters &m_parameters;
401 unsigned m_lastDepth;
404 #endif // SYMBOLGROUPNODE_H