V-Gears 0
Free Final Fantasy VII engine.
Graph.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2022 The V-Gears Team
3 *
4 * This file is part of V-Gears
5 *
6 * V-Gears is free software: you can redistribute it and/or modify it under
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, version 3.0 (GPLv3) of the License.
9 *
10 * V-Gears is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#pragma once
17
18#include <ostream>
19#include <utility>
20#include <vector>
21#include <boost/format.hpp>
22#include <boost/version.hpp>
23#ifdef _MSC_VER
24#pragma warning (push)
25#pragma warning(disable:4512)
26#pragma warning(disable:4100)
27#endif
28#include <boost/graph/graph_traits.hpp>
29#include <boost/graph/adjacency_list.hpp>
30#include <boost/graph/graphviz.hpp>
31#ifdef _MSC_VER
32#pragma warning (pop)
33#endif
34#include <boost/intrusive_ptr.hpp>
36#include "RefCounted.h"
37
42
47
52
57
62
67
72};
73
74struct Group;
75
76typedef boost::intrusive_ptr<Group> GroupPtr;
77
78typedef boost::property<boost::vertex_name_t, GroupPtr> GroupProperty;
79
80typedef boost::property<boost::vertex_index_t, int, GroupProperty> GraphProperty;
81
85struct IsJump {
86
90 bool is_jump = false;
91
97 IsJump();
98
104 IsJump(bool jump);
105
113 friend std::ostream &operator<<(std::ostream &output, IsJump is_jump){
114 if (is_jump.is_jump) output << "empty";
115 else output << "normal";
116 return output;
117 }
118};
119
120namespace boost {
121
125 template <class Name> class ArrowheadWriter{
126
127 public:
128
134 explicit ArrowheadWriter(Name name): name(name){}
135
142 template <class VertexOrEdge> void operator()(
143 std::ostream& out, const VertexOrEdge& v
144 ) const {
145 out << "[arrowhead=\"" << get(name, v) << "\"]";
146 }
147
148 private:
149
153 Name name;
154 };
155
161 template <class Name> inline ArrowheadWriter<Name> MakeArrowheadWriter(Name n) {
162 return ArrowheadWriter<Name>(n);
163 }
164
165}
166
167typedef boost::property<boost::edge_attribute_t, IsJump> EdgeProperty;
168
169typedef boost::adjacency_list<boost::setS, boost::listS, boost::bidirectionalS, GraphProperty, EdgeProperty> Graph;
170
171typedef Graph::vertex_descriptor GraphVertex;
172
173typedef Graph::vertex_iterator VertexIterator;
174
175typedef Graph::edge_descriptor GraphEdge;
176
177typedef Graph::out_edge_iterator OutEdgeIterator;
178
179typedef Graph::in_edge_iterator InEdgeIterator;
180
181typedef std::pair<VertexIterator, VertexIterator> VertexRange;
182
183typedef std::pair<OutEdgeIterator, OutEdgeIterator> OutEdgeRange;
184
185typedef std::pair<InEdgeIterator, InEdgeIterator> InEdgeRange;
186
190struct CodeLine {
191
195 std::string line = "0";
196
200 bool unindent_before = false;
201
205 bool indent_after = false;
206
216 CodeLine(const std::string& line, bool unindent_before, bool indent_after);
217};
218
219typedef std::vector<Group *> ElseEnds; // Weak references to groups ending else blocks.
220
221typedef ElseEnds::iterator ElseEndIterator;
222
226struct Group : public RefCounted {
227
232
237
242
247
252
257
262
269
274
278 std::vector<CodeLine> code;
279
288
294 Group();
295
306
314 friend std::ostream &operator<<(std::ostream &output, GroupPtr group){
315 output << "{Block type: ";
316 switch(group->type) {
317 case GROUP_TYPE_NORMAL: output << "Normal"; break;
318 case GROUP_TYPE_WHILE: output << "While condition"; break;
319 case GROUP_TYPE_DO_WHILE: output << "Do-while condition"; break;
320 case GROUP_TYPE_IF: output << "If condition"; break;
321 case GROUP_TYPE_BREAK: output << "Break"; break;
322 case GROUP_TYPE_CONTINUE: output << "Continue"; break;
323 }
324 output << "\\n";
325 output << "Expected stack level: " << group->stack_level << "\\n";
326 if (group->start_else) output << "Start of else\\n";
327 for (ElseEndIterator it = group->end_else.begin(); it != group->end_else.end(); ++ it)
328 output << boost::format("End of else at %08x\\n") % (*(*it)->start)->GetAddress();
329 output << "|";
330 ConstInstIterator inst = group->start;
331 do {
332 std::stringstream stream;
333 stream << *inst;
334#if (BOOST_VERSION >= 104500)
335 output << stream.str();
336#else
337 std::string s = stream.str();
338 for (std::string::iterator it = s.begin(); it != s.end(); ++it)
339 if (*it == '"') output << "\\\"";
340 else if (*it == '|') output << "\\|";
341 else if (*it == '{') output << "\\{";
342 else if (*it == '}') output << "\\}";
343 else output << *it;
344#endif
345 output << "\\n";
346 } while (inst ++ != group->end);
347 output << "}";
348 return output;
349 }
350};
351
352class Engine;
353
358
359 public:
360
369
376
383
391 void operator()(std::ostream& out) const;
392
393 private:
394
399
403 const Graph* graph;
404};
405
GROUP_TYPE
Enumeration representing the different kinds of groups.
Definition: Graph.h:41
@ GROUP_TYPE_NORMAL
Normal group.
Definition: Graph.h:46
@ GROUP_TYPE_DO_WHILE
Group is the condition check for a do-while-loop.
Definition: Graph.h:56
@ GROUP_TYPE_CONTINUE
Group is a continue.
Definition: Graph.h:71
@ GROUP_TYPE_BREAK
Group is a break.
Definition: Graph.h:66
@ GROUP_TYPE_WHILE
Group is the condition check for a while-loop.
Definition: Graph.h:51
@ GROUP_TYPE_IF
Group is the condition check for an if.
Definition: Graph.h:61
boost::property< boost::vertex_index_t, int, GroupProperty > GraphProperty
Definition: Graph.h:80
boost::intrusive_ptr< Group > GroupPtr
Definition: Graph.h:76
boost::property< boost::edge_attribute_t, IsJump > EdgeProperty
Definition: Graph.h:167
Graph::edge_descriptor GraphEdge
Definition: Graph.h:175
std::pair< OutEdgeIterator, OutEdgeIterator > OutEdgeRange
Definition: Graph.h:183
Graph::in_edge_iterator InEdgeIterator
Definition: Graph.h:179
Graph::vertex_iterator VertexIterator
Definition: Graph.h:173
Graph::vertex_descriptor GraphVertex
Definition: Graph.h:171
ElseEnds::iterator ElseEndIterator
Definition: Graph.h:221
boost::adjacency_list< boost::setS, boost::listS, boost::bidirectionalS, GraphProperty, EdgeProperty > Graph
Definition: Graph.h:169
std::pair< InEdgeIterator, InEdgeIterator > InEdgeRange
Definition: Graph.h:185
std::pair< VertexIterator, VertexIterator > VertexRange
Definition: Graph.h:181
Graph::out_edge_iterator OutEdgeIterator
Definition: Graph.h:177
boost::property< boost::vertex_name_t, GroupPtr > GroupProperty
Definition: Graph.h:78
std::vector< Group * > ElseEnds
Definition: Graph.h:219
InstVec::iterator InstIterator
Type representing an iterator over InstPtrs.
Definition: Instruction.h:387
InstVec::const_iterator ConstInstIterator
Type representing a const_iterator over InstPtrs.
Definition: Instruction.h:392
Base class for engines.
Definition: Engine.h:34
Provides a base implementation of reference counting.
Definition: RefCounted.h:28
Property writer for the IsJump property.
Definition: Graph.h:125
Name name
The name of the attribute to use.
Definition: Graph.h:153
void operator()(std::ostream &out, const VertexOrEdge &v) const
Outputs the arrowhead edge property.
Definition: Graph.h:142
ArrowheadWriter(Name name)
Constructor.
Definition: Graph.h:134
Definition: Graph.h:120
ArrowheadWriter< Name > MakeArrowheadWriter(Name n)
Creates an arrowhead property writer.
Definition: Graph.h:161
Structure representing a line of code.
Definition: Graph.h:190
bool indent_after
Whether to remove an indentation level after outputting the line.
Definition: Graph.h:205
bool unindent_before
Whether or not to add an indentation level before outputting the line.
Definition: Graph.h:200
std::string line
The line of code.
Definition: Graph.h:195
CodeLine(const std::string &line, bool unindent_before, bool indent_after)
Constructor for CodeLine.
Definition: Graph.cpp:24
Type used to set properties for dot output.
Definition: Graph.h:357
Engine * engine
Engine containing function information for the script.
Definition: Graph.h:398
GraphProperties(Engine *engine, const Graph &graph)
Constructor.
Definition: Graph.cpp:42
GraphProperties & operator=(const GraphProperties &rhs)
Copy constructor.
Definition: Graph.cpp:47
void operator()(std::ostream &out) const
Print properties of the graph.
Definition: Graph.cpp:55
const Graph * graph
Pointer to the to the graph for the script.
Definition: Graph.h:403
Structure representing a group of instructions.
Definition: Graph.h:226
int stack_level
Level of the stack upon entry.
Definition: Graph.h:246
GROUP_TYPE type
Type of the group.
Definition: Graph.h:251
std::vector< CodeLine > code
Decompiled lines of code.
Definition: Graph.h:278
Group * prev
Pointer to the previous group, when ordered by address.
Definition: Graph.h:268
InstIterator end
Last instruction in the group.
Definition: Graph.h:241
Group()
Parameterless constructor.
Definition: Graph.cpp:27
InstIterator start
First instruction in the group.
Definition: Graph.h:236
friend std::ostream & operator<<(std::ostream &output, GroupPtr group)
Output a group to an stream as a graphviz label.
Definition: Graph.h:314
Group * next
Pointer to the next group, when ordered by address.
Definition: Graph.h:273
bool start_else
Group is start of an else block.
Definition: Graph.h:256
bool coalesced_else
Indicates if an starting else coalesces with another block.
Definition: Graph.h:287
ElseEnds end_else
Group is end of an else block.
Definition: Graph.h:261
GraphVertex vertex
Vertex the group belongs to.
Definition: Graph.h:231
Structure representing whether or not an edge is a jump.
Definition: Graph.h:85
friend std::ostream & operator<<(std::ostream &output, IsJump is_jump)
Output edge information as a graphviz edge property.
Definition: Graph.h:113
bool is_jump
Whether or not the edge is a jump.
Definition: Graph.h:90
IsJump()
Parameterless constructor.
Definition: Graph.cpp:20