Fix for UBSan build
[platform/upstream/doxygen.git] / src / dot.h
1 /******************************************************************************
2  *
3  * $Id: dot.h,v 1.14 2001/03/19 19:27:40 root Exp $
4  *
5  *
6  * Copyright (C) 1997-2012 by Dimitri van Heesch.
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation under the terms of the GNU General Public License is hereby 
10  * granted. No representations are made about the suitability of this software 
11  * for any purpose. It is provided "as is" without express or implied warranty.
12  * See the GNU General Public License for more details.
13  *
14  * Documents produced by Doxygen are derivative works derived from the
15  * input used in their production; they are not affected by this license.
16  *
17  */
18
19 #ifndef _DOT_H
20 #define _DOT_H
21
22 #include "qtbc.h"
23 #include <qlist.h>
24 #include <qdict.h>
25 #include <qwaitcondition.h>
26 #include <qmutex.h>
27 #include <qqueue.h>
28 #include <qthread.h>
29 #include "sortdict.h"
30
31 class ClassDef;
32 class FileDef;
33 class FTextStream;
34 class DotNodeList;
35 class ClassSDict;
36 class MemberDef;
37 class Definition;
38 class DirDef;
39 class GroupDef;
40 class DotGroupCollaboration;
41 class DotRunnerQueue;
42
43 enum GraphOutputFormat { BITMAP , EPS };
44
45 /** Attributes of an edge of a dot graph */
46 struct EdgeInfo
47 {
48   enum Colors { Blue=0, Green=1, Red=2, Purple=3, Grey=4, Orange=5 };
49   enum Styles { Solid=0, Dashed=1 };
50   EdgeInfo() : m_color(0), m_style(0), m_labColor(0) {}
51  ~EdgeInfo() {}
52   int m_color;
53   int m_style;
54   QCString m_label;
55   QCString m_url;
56   int m_labColor;
57 };
58
59 /** A node in a dot graph */
60 class DotNode
61 {
62   public:
63     enum GraphType { Dependency, Inheritance, Collaboration, Hierarchy, CallGraph };
64     enum TruncState { Unknown, Truncated, Untruncated };
65     DotNode(int n,const char *lab,const char *tip,const char *url,
66             bool rootNode=FALSE,ClassDef *cd=0);
67    ~DotNode();
68     void addChild(DotNode *n,
69                   int edgeColor=EdgeInfo::Purple,
70                   int edgeStyle=EdgeInfo::Solid,
71                   const char *edgeLab=0,
72                   const char *edgeURL=0,
73                   int edgeLabCol=-1
74                  );
75     void addParent(DotNode *n);
76     void deleteNode(DotNodeList &deletedList,SDict<DotNode> *skipNodes=0);
77     void removeChild(DotNode *n);
78     void removeParent(DotNode *n);
79     int findParent( DotNode *n );
80     void write(FTextStream &t,GraphType gt,GraphOutputFormat f,
81                bool topDown,bool toChildren,bool backArrows,bool reNumber);
82     int  m_subgraphId;
83     void clearWriteFlag();
84     void writeXML(FTextStream &t,bool isClassGraph);
85     void writeDEF(FTextStream &t);
86     QCString label() const { return m_label; }
87     int  number() const { return m_number; }
88     bool isVisible() const { return m_visible; }
89     TruncState isTruncated() const { return m_truncated; }
90     int distance() const { return m_distance; }
91
92   private:
93     void colorConnectedNodes(int curColor);
94     void writeBox(FTextStream &t,GraphType gt,GraphOutputFormat f,
95                   bool hasNonReachableChildren, bool reNumber=FALSE);
96     void writeArrow(FTextStream &t,GraphType gt,GraphOutputFormat f,DotNode *cn,
97                     EdgeInfo *ei,bool topDown, bool pointBack=TRUE, bool reNumber=FALSE);
98     void setDistance(int distance);
99     const DotNode   *findDocNode() const; // only works for acyclic graphs!
100     void markAsVisible(bool b=TRUE) { m_visible=b; }
101     void markAsTruncated(bool b=TRUE) { m_truncated=b ? Truncated : Untruncated; }
102     int              m_number;
103     QCString         m_label;     //!< label text
104     QCString         m_tooltip;   //!< node's tooltip
105     QCString         m_url;       //!< url of the node (format: remote$local)
106     QList<DotNode>  *m_parents;   //!< list of parent nodes (incoming arrows)
107     QList<DotNode>  *m_children;  //!< list of child nodes (outgoing arrows)
108     QList<EdgeInfo> *m_edgeInfo;  //!< edge info for each child
109     bool             m_deleted;   //!< used to mark a node as deleted
110     bool             m_written;   //!< used to mark a node as written
111     bool             m_hasDoc;    //!< used to mark a node as documented
112     bool             m_isRoot;    //!< indicates if this is a root node
113     ClassDef *       m_classDef;  //!< class representing this node (can be 0)
114     bool             m_visible;   //!< is the node visible in the output
115     TruncState       m_truncated; //!< does the node have non-visible children/parents
116     int              m_distance;  //!< shortest path to the root node
117
118     friend class DotGfxHierarchyTable;
119     friend class DotClassGraph;
120     friend class DotInclDepGraph;
121     friend class DotNodeList;
122     friend class DotCallGraph;
123     friend class DotGroupCollaboration;
124
125     friend QCString computeMd5Signature(
126                       DotNode *root, GraphType gt,
127                       GraphOutputFormat f, 
128                       bool lrRank, bool renderParents,
129                       bool backArrows,
130                       const QCString &title,
131                       QCString &graphStr
132                      );
133 };
134
135 inline int DotNode::findParent( DotNode *n )
136 {
137     if( !m_parents )
138         return -1;
139     return m_parents->find(n);
140 }
141
142 /** Represents a graphical class hierarchy */
143 class DotGfxHierarchyTable
144 {
145   public:
146     DotGfxHierarchyTable();
147    ~DotGfxHierarchyTable();
148     void writeGraph(FTextStream &t,const char *path, const char *fileName) const;
149   
150   private:
151     void addHierarchy(DotNode *n,ClassDef *cd,bool hide);
152     void addClassList(ClassSDict *cl);
153
154     QList<DotNode> *m_rootNodes; 
155     QDict<DotNode> *m_usedNodes; 
156     static int      m_curNodeNumber;
157     DotNodeList    *m_rootSubgraphs;
158 };
159
160 /** Representation of a class inheritance or dependency graph */
161 class DotClassGraph
162 {
163   public:
164     DotClassGraph(ClassDef *cd,DotNode::GraphType t);
165    ~DotClassGraph();
166     bool isTrivial() const;
167     bool isTooBig() const;
168     QCString writeGraph(FTextStream &t,GraphOutputFormat f,const char *path,
169                     const char *fileName, const char *relPath, 
170                     bool TBRank=TRUE,bool imageMap=TRUE,int graphId=-1) const;
171
172     void writeXML(FTextStream &t);
173     void writeDEF(FTextStream &t);
174     QCString diskName() const;
175
176   private:
177     void buildGraph(ClassDef *cd,DotNode *n,bool base,int distance);
178     bool determineVisibleNodes(DotNode *rootNode,int maxNodes,bool includeParents);
179     void determineTruncatedNodes(QList<DotNode> &queue,bool includeParents);
180     void addClass(ClassDef *cd,DotNode *n,int prot,const char *label,
181                   const char *usedName,const char *templSpec,
182                   bool base,int distance);
183
184     DotNode        *   m_startNode;
185     QDict<DotNode> *   m_usedNodes;
186     static int         m_curNodeNumber;
187     DotNode::GraphType m_graphType;
188     QCString           m_diskName;
189     bool               m_lrRank;
190 };
191
192 /** Representation of an include dependency graph */
193 class DotInclDepGraph
194 {
195   public:
196     DotInclDepGraph(FileDef *fd,bool inverse);
197    ~DotInclDepGraph();
198     QCString writeGraph(FTextStream &t, GraphOutputFormat f,
199                     const char *path,const char *fileName,const char *relPath,
200                     bool writeImageMap=TRUE,int graphId=-1) const;
201     bool isTrivial() const;
202     bool isTooBig() const;
203     QCString diskName() const;
204     void writeXML(FTextStream &t);
205
206   private:
207     void buildGraph(DotNode *n,FileDef *fd,int distance);
208     void determineVisibleNodes(QList<DotNode> &queue,int &maxNodes);
209     void determineTruncatedNodes(QList<DotNode> &queue);
210
211     DotNode        *m_startNode;
212     QDict<DotNode> *m_usedNodes;
213     static int      m_curNodeNumber;
214     QCString        m_diskName;
215     int             m_maxDistance;
216     bool            m_inverse;
217 };
218
219 /** Representation of an call graph */
220 class DotCallGraph
221 {
222   public:
223     DotCallGraph(MemberDef *md,bool inverse);
224    ~DotCallGraph();
225     QCString writeGraph(FTextStream &t, GraphOutputFormat f,
226                         const char *path,const char *fileName,
227                         const char *relPath,bool writeImageMap=TRUE,
228                         int graphId=-1) const;
229     void buildGraph(DotNode *n,MemberDef *md,int distance);
230     bool isTrivial() const;
231     bool isTooBig() const;
232     void determineVisibleNodes(QList<DotNode> &queue, int &maxNodes);
233     void determineTruncatedNodes(QList<DotNode> &queue);
234     
235   private:
236     DotNode        *m_startNode;
237     static int      m_curNodeNumber;
238     QDict<DotNode> *m_usedNodes;
239     int             m_maxDistance;
240     int             m_recDepth;
241     bool            m_inverse;
242     QCString        m_diskName;
243     Definition *    m_scope;
244 };
245
246 /** Representation of an directory dependency graph */
247 class DotDirDeps
248 {
249   public:
250     DotDirDeps(DirDef *dir);
251    ~DotDirDeps();
252     bool isTrivial() const;
253     QCString writeGraph(FTextStream &out,
254                         GraphOutputFormat format,
255                         const char *path,
256                         const char *fileName,
257                         const char *relPath,
258                         bool writeImageMap=TRUE,
259                         int graphId=-1) const;
260   private:
261     DirDef *m_dir;
262 };
263
264 /** Representation of a group collaboration graph */
265 class DotGroupCollaboration
266 {
267   public :
268     enum EdgeType 
269     {  tmember = 0,
270        tclass,
271        tnamespace,
272        tfile,
273        tpages,
274        tdir,
275        thierarchy 
276     };
277
278     class Link
279     {
280       public:
281         Link(const QCString lab,const QCString &u) : label(lab), url(u) {}
282         QCString label;
283         QCString url;
284     };
285
286     class Edge
287     {
288       public :
289         Edge(DotNode *start,DotNode *end,EdgeType type) 
290           : pNStart(start), pNEnd(end), eType(type)
291         { links.setAutoDelete(TRUE); }
292
293         DotNode* pNStart;
294         DotNode* pNEnd;
295         EdgeType eType;
296
297         QList<Link> links;
298         void write( FTextStream &t ) const;
299     };
300
301     DotGroupCollaboration(GroupDef* gd);
302     ~DotGroupCollaboration();
303     QCString writeGraph(FTextStream &t, GraphOutputFormat format,
304                     const char *path,const char *fileName,const char *relPath,
305                     bool writeImageMap=TRUE,int graphId=-1) const;
306     void buildGraph(GroupDef* gd);
307     bool isTrivial() const;
308   private :
309     void addCollaborationMember( Definition* def, QCString& url, EdgeType eType );
310     void addMemberList( class MemberList* ml );
311     void writeGraphHeader(FTextStream &t,const QCString &title) const;
312     Edge* addEdge( DotNode* _pNStart, DotNode* _pNEnd, EdgeType _eType,
313                    const QCString& _label, const QCString& _url );
314
315     DotNode        *m_rootNode;
316     int             m_curNodeId;
317     QDict<DotNode> *m_usedNodes;
318     QCString        m_diskName;
319     QList<Edge>     m_edges;
320 };
321
322 /** Helper class to run dot from doxygen.
323  */
324 class DotRunner
325 {
326   public:
327     struct CleanupItem
328     {
329       QCString path;
330       QCString file;
331     };
332
333     /** Creates a runner for a dot \a file. */
334     DotRunner(const QCString &file,const QCString &fontPath,bool checkResult,
335         const QCString &imageName = QCString());
336
337     /** Adds an additional job to the run.
338      *  Performing multiple jobs one file can be faster.
339      */
340     void addJob(const char *format,const char *output);
341
342     void addPostProcessing(const char *cmd,const char *args);
343
344     void preventCleanUp() { m_cleanUp = FALSE; }
345
346     /** Runs dot for all jobs added. */
347     bool run();
348     CleanupItem cleanup() const { return m_cleanupItem; }
349
350   private:
351     QList<QCString> m_jobs;
352     QCString m_postArgs;
353     QCString m_postCmd;
354     QCString m_file;
355     QCString m_path;
356     bool m_checkResult;
357     QCString m_imageName;
358     bool m_cleanUp;
359     CleanupItem m_cleanupItem;
360 };
361
362 /** Helper class to insert a set of map file into an output file */
363 class DotFilePatcher
364 {
365   public:
366     struct Map
367     {
368       QCString mapFile;
369       QCString relPath;
370       bool     urlOnly;
371       QCString context;
372       QCString label;
373       bool     zoomable;
374       int      graphId;
375     };
376     DotFilePatcher(const char *patchFile);
377     int addMap(const QCString &mapFile,const QCString &relPath,
378                bool urlOnly,const QCString &context,const QCString &label);
379     int addFigure(const QCString &baseName,
380                   const QCString &figureName,bool heightCheck);
381     int addSVGConversion(const QCString &relPath,bool urlOnly,
382                          const QCString &context,bool zoomable,int graphId);
383     int addSVGObject(const QCString &baseName, const QCString &figureName,
384                      const QCString &relPath);
385     bool run();
386     QCString file() const;
387
388   private:
389     QList<Map> m_maps;
390     QCString m_patchFile;
391 };
392
393 /** Queue of dot jobs to run. */
394 class DotRunnerQueue
395 {
396   public:
397     void enqueue(DotRunner *runner);
398     DotRunner *dequeue();
399     uint count() const;
400   private:
401     QWaitCondition  m_bufferNotEmpty;
402     QQueue<DotRunner> m_queue;
403     mutable QMutex  m_mutex;
404 };
405
406 /** Worker thread to execute a dot run */
407 class DotWorkerThread : public QThread
408 {
409   public:
410     DotWorkerThread(int id,DotRunnerQueue *queue);
411     void run();
412     void cleanup();
413   private:
414     int m_id;
415     DotRunnerQueue *m_queue;
416     QList<DotRunner::CleanupItem> m_cleanupItems;
417 };
418
419 /** Singleton that manages dot relation actions */
420 class DotManager
421 {
422   public:
423     static DotManager *instance();
424     void addRun(DotRunner *run);
425     int  addMap(const QCString &file,const QCString &mapFile,
426                 const QCString &relPath,bool urlOnly,
427                 const QCString &context,const QCString &label);
428     int addFigure(const QCString &file,const QCString &baseName,
429                   const QCString &figureName,bool heightCheck);
430     int addSVGConversion(const QCString &file,const QCString &relPath,
431                bool urlOnly,const QCString &context,bool zoomable,int graphId);
432     int addSVGObject(const QCString &file,const QCString &baseName,
433                      const QCString &figureNAme,const QCString &relPath);
434     bool run();
435
436   private:
437     DotManager();
438     virtual ~DotManager();
439     QList<DotRunner>       m_dotRuns;
440     SDict<DotFilePatcher> m_dotMaps;
441     static DotManager     *m_theInstance;
442     DotRunnerQueue        *m_queue;
443     QList<DotWorkerThread> m_workers;
444 };
445
446
447 /** Generated a graphs legend page */
448 void generateGraphLegend(const char *path);
449
450 void writeDotGraphFromFile(const char *inFile,const char *outDir,
451                            const char *outFile,GraphOutputFormat format);
452 void writeDotImageMapFromFile(FTextStream &t,
453                               const QCString& inFile, const QCString& outDir,
454                               const QCString& relPath,const QCString& baseName,
455                               const QCString& context,int graphId=-1);
456
457 void writeDotDirDepGraph(FTextStream &t,DirDef *dd);
458
459 #endif