[Scummvm-cvs-logs] SF.net SVN: scummvm:[42003] tools/branches/gsoc2009-decompiler/decompiler
kjdf at users.sourceforge.net
kjdf at users.sourceforge.net
Wed Jul 1 19:18:55 CEST 2009
Revision: 42003
http://scummvm.svn.sourceforge.net/scummvm/?rev=42003&view=rev
Author: kjdf
Date: 2009-07-01 17:18:54 +0000 (Wed, 01 Jul 2009)
Log Message:
-----------
decompiler: separated graph.h into .cpp and added some documentation
Modified Paths:
--------------
tools/branches/gsoc2009-decompiler/decompiler/Makefile
tools/branches/gsoc2009-decompiler/decompiler/graph.h
tools/branches/gsoc2009-decompiler/decompiler/instruction.h
tools/branches/gsoc2009-decompiler/decompiler/misc.h
Added Paths:
-----------
tools/branches/gsoc2009-decompiler/decompiler/graph.cpp
tools/branches/gsoc2009-decompiler/decompiler/misc.cpp
Modified: tools/branches/gsoc2009-decompiler/decompiler/Makefile
===================================================================
--- tools/branches/gsoc2009-decompiler/decompiler/Makefile 2009-07-01 17:13:46 UTC (rev 42002)
+++ tools/branches/gsoc2009-decompiler/decompiler/Makefile 2009-07-01 17:18:54 UTC (rev 42003)
@@ -75,7 +75,7 @@
.PHONY: all clean test
-decompiler$(EXEEXT): decompiler.o
+decompiler$(EXEEXT): decompiler.o graph.o misc.o
$(CXX) $(LDFLAGS) -o $@ $+ -lboost_program_options
decompiler.o: graph.h instruction.h misc.h parser.h reader.h
Added: tools/branches/gsoc2009-decompiler/decompiler/graph.cpp
===================================================================
--- tools/branches/gsoc2009-decompiler/decompiler/graph.cpp (rev 0)
+++ tools/branches/gsoc2009-decompiler/decompiler/graph.cpp 2009-07-01 17:18:54 UTC (rev 42003)
@@ -0,0 +1,249 @@
+#include <algorithm>
+
+#include "graph.h"
+
+using namespace std;
+
+
+
+ControlFlowGraph::ControlFlowGraph() : _entry() {
+}
+
+
+ControlFlowGraph::~ControlFlowGraph() {
+ foreach (Block *u, _blocks)
+ delete u;
+}
+
+
+void ControlFlowGraph::addEdge(Block *from, Block *to) {
+ from->_out.push_back(to);
+ to->_in.push_back(from);
+}
+
+
+// entry node is an interval header
+// a node belongs to an interval, if all its immediate predecessors belong the given interval
+// otherwise it is an interval header
+void ControlFlowGraph::assignIntervals() {
+ std::list<Block*> intervals;
+ intervals.push_back(_entry);
+ foreach (Block *interval, intervals) {
+ interval->_interval = interval;
+ for (bool added = true; added; ) {
+ added = false;
+ foreach (Block *m, _blocks) {
+ bool allPredInInterval = true;
+ foreach (Block *p, m->_in)
+ allPredInInterval &= p->_interval == interval;
+ if (!m->_interval && allPredInInterval) {
+ added = true;
+ m->_interval = interval;
+ }
+ }
+ }
+ foreach (Block *m, _blocks) {
+ bool anyPredInInterval = false;
+ foreach (Block *p, m->_in)
+ anyPredInInterval |= p->_interval == interval;
+ if (!m->_interval && anyPredInInterval)
+ intervals.push_back(m);
+ }
+ }
+}
+
+
+// a derived graph, given set of intervals, is a graph in which
+// all intervals have been collapsed to a single node, and edge
+// exists between nodes if there are edges crossing corresponding
+// intervals in the original graph
+void ControlFlowGraph::extendIntervals() {
+ ControlFlowGraph d;
+ std::map<Block*, Block*> trans;
+ foreach (Block *interval, intervals()) {
+ trans[interval] = d.addBlock(interval->_instructions.begin(), interval->_instructions.end());
+ trans[interval]->_primitive = interval;
+ }
+ foreach (Block *interval, intervals())
+ foreach (Block *u, interval->_in)
+ if (u->_interval != interval)
+ d.addEdge(trans[u->_interval], trans[interval]);
+ d.setEntry(_entry->_instructions.front()->_addr);
+ d.assignIntervals();
+ foreach (Block *du, d._blocks)
+ foreach (Block *v, _blocks)
+ if (v->_interval == du->_primitive)
+ v->_interval = du->_interval->_primitive;
+}
+
+
+string ControlFlowGraph::graphvizEscapeLabel(const std::string &s) {
+ std::string ret;
+ foreach (char c, s) {
+ if (c == '\n' || c == '"' || c == '\\')
+ ret.push_back('\\');
+ ret.push_back(c == '\n' ? 'l' : c); // align lines to the left
+ }
+ return ret;
+}
+
+
+string ControlFlowGraph::graphvizToString(const std::string &fontname, int fontsize) {
+ std::stringstream ret;
+ ret << "digraph G {" << std::endl;
+ foreach (Block *interval, intervals()) {
+ ret << "subgraph " << '"' << "cluster_" << interval << '"' << " {" << std::endl;
+ ret << "style=dotted;" << std::endl;
+ foreach (Block *u, _blocks)
+ if (u->_interval == interval) {
+ ret << '"' << u << "\"[";
+ if (fontname != "")
+ ret << "fontname=" << '"' << fontname << "\",";
+ if (fontsize != 0)
+ ret << "fontsize=" << fontsize << ",";
+ ret << "shape=box,label=\"<number: " << u->_number;
+ if (u->_loopFollow)
+ ret << ", loop_type=" << (u->_loopType == PRE_TESTED ? "pre_tested" : u->_loopType == POST_TESTED ? "post_tested" : "endless");
+ ret << ">\\n" << graphvizEscapeLabel(u->toString()) << "\"];" << std::endl;
+ }
+ ret << "}" << std::endl;
+ }
+ foreach (Block *u, _blocks)
+ foreach (Block *v, u->_out)
+ ret << '"' << u << "\" -> \"" << v << '"' << (v == u->_loopFollow ? "[color=blue]" : "") << ";" << std::endl;
+ ret << "}" << std::endl;
+ return ret.str();
+}
+
+
+bool ControlFlowGraph::inLoop(Block *head, Block *latch, Block *u) {
+ return u->_interval == head && latch->_number <= u->_number && u->_number < head->_number;
+}
+
+
+list<Block*> ControlFlowGraph::intervals() {
+ std::list<Block*> ret;
+ assignIntervals();
+ foreach (Block *u, _blocks)
+ if (u->_interval == u)
+ ret.push_back(u);
+ return ret;
+}
+
+
+Block *ControlFlowGraph::loopFollow(Block *head, Block *latch) {
+ if (head->_loopType == PRE_TESTED)
+ return head->_out.front();
+ if (head->_loopType == POST_TESTED)
+ return latch->_out.back();
+ // ENDLESS
+ Block *ret = 0;
+ foreach (Block *u, _blocks)
+ if (inLoop(head, latch, u) && u->_out.size() == 2 && (!ret || ret->_number < u->_out.back()->_number))
+ ret = u->_out.back();
+ return ret;
+}
+
+
+// for each set of 'growing' intervals in derived sequence of graphs,
+// every interval header is a potential loop header
+// we check for back edges that don't belong to loops discovered earlier
+// (inner loops)
+void ControlFlowGraph::loopStruct() {
+ for (size_t size = _blocks.size()+1; size > intervals().size(); size = intervals().size(), extendIntervals())
+ foreach (Block *interval, intervals()) {
+ foreach (Block *latch, interval->_in) {
+ if (latch->_interval == interval && !latch->_loopHead) {
+ foreach (Block *u, _blocks)
+ if (inLoop(interval, latch, u))
+ u->_loopHead = interval;
+ interval->_loopLatch = latch; // TODO do we need this?
+ interval->_loopType = loopType(interval, latch);
+ interval->_loopFollow = loopFollow(interval, latch);
+ }
+ }
+ }
+}
+
+
+LoopType ControlFlowGraph::loopType(Block *head, Block *latch) {
+ if (head->_out.size() == 1 && latch->_out.size() == 1)
+ return ENDLESS;
+ if (head->_out.size() == 1 && latch->_out.size() == 2)
+ return POST_TESTED;
+ if (head->_out.size() == 2 && latch->_out.size() == 1)
+ return PRE_TESTED;
+ // head->_out.size() == 2 && latch->_out.size() == 2
+ if (inLoop(head, latch, head->_out.front()))
+ return POST_TESTED;
+ else
+ return PRE_TESTED;
+}
+
+
+void ControlFlowGraph::orderBlocks() {
+ assert(_entry);
+ orderVisit(_entry, 0);
+}
+
+
+int ControlFlowGraph::orderVisit(Block *u, int number) {
+ u->_number = -1;
+ foreach (Block *v, u->_out)
+ if (!v->_number)
+ number = orderVisit(v, number);
+ u->_number = ++number;
+ return number;
+}
+
+
+void ControlFlowGraph::removeJumpsToJumps() {
+ for (bool changed = true; changed; ) {
+ changed = false;
+ foreach (Block *u, _blocks) {
+ foreach (Block *v, u->_out) {
+ Jump *jump = dynamic_cast<Jump*>(v->_instructions.front());
+ if (jump && !dynamic_cast<CondJump*>(jump) && jump->target() != jump->_addr) {
+ changed = true;
+ replaceEdges(u, v, _targets[jump->target()]);
+ }
+ }
+ }
+ }
+}
+
+
+// there are no paths that lead from entries to an unreachable node
+// but unreachable node can still have outgoing edge to the main part
+// of the graph, and we need to remove it from predecessor lists
+void ControlFlowGraph::removeUnreachableBlocks() {
+ foreach (Block *u, _blocks)
+ if (!u->_number) {
+ foreach (Block *v, u->_out)
+ v->_in.remove(u);
+ }
+ for (list<Block*>::iterator it = _blocks.begin(); it != _blocks.end(); )
+ if ((*it)->_number)
+ it++;
+ else {
+ delete *it;
+ it = _blocks.erase(it);
+ }
+}
+
+
+void ControlFlowGraph::replaceEdges(Block *from, Block *oldTo, Block *newTo) {
+ size_t n = count(oldTo->_in.begin(), oldTo->_in.end(), from);
+ oldTo->_in.remove(from);
+ fill_n(back_inserter(newTo->_in), n, from);
+ foreach (Block *&block, from->_out)
+ if (block == oldTo)
+ block = newTo;
+}
+
+
+void ControlFlowGraph::setEntry(address_t entry) {
+ foreach (Block *block, _blocks)
+ if (block->_instructions.front()->_addr == entry)
+ _entry = block;
+}
Property changes on: tools/branches/gsoc2009-decompiler/decompiler/graph.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:eol-style
+ native
Modified: tools/branches/gsoc2009-decompiler/decompiler/graph.h
===================================================================
--- tools/branches/gsoc2009-decompiler/decompiler/graph.h 2009-07-01 17:13:46 UTC (rev 42002)
+++ tools/branches/gsoc2009-decompiler/decompiler/graph.h 2009-07-01 17:18:54 UTC (rev 42003)
@@ -1,14 +1,15 @@
#ifndef GRAPH_H
#define GRAPH_H
-#include "misc.h"
#include <cassert>
+#include <iostream>
#include <list>
#include <map>
#include <set>
#include <sstream>
-#include <iostream>
+#include "instruction.h"
+#include "misc.h"
enum LoopType {
PRE_TESTED,
@@ -19,19 +20,19 @@
struct Block : boost::noncopyable {
- Block *_interval;
- Block *_loopFollow;
- Block *_loopHead;
- Block *_loopLatch;
- Block *_primitive;
+ Block *_interval; // header node of the interval this block belongs to
+ Block *_loopFollow; // if not null, this block is a loop header, and follow is a first block after exit
+ Block *_loopHead; // if not null, this block belongs to a loop
+ Block *_loopLatch; // if not null, this block is a loop header, and latch is the last block in the loop
+ Block *_primitive; // interval header of the graph from which this graph has been derived
LoopType _loopType;
- int _number;
- list<Block*> _in;
- list<Block*> _out;
- list<Instruction*> _instructions;
+ int _number; // number in reverse post-order
+ std::list<Block*> _in;
+ std::list<Block*> _out;
+ std::list<Instruction*> _instructions;
- string toString() {
- ostringstream ret;
+ std::string toString() {
+ std::ostringstream ret;
foreach (Instruction *instruction, _instructions)
ret << instruction->toString();
return ret.str();
@@ -49,16 +50,21 @@
Block *_entry;
std::list<Block*> _blocks;
- map<address_t, Block*> _targets;
+ std::map<address_t, Block*> _targets; // helps partitioning code into basic blocks
- ControlFlowGraph() : _entry() {
- }
+ ControlFlowGraph();
+ ~ControlFlowGraph();
- ~ControlFlowGraph() {
- foreach (Block *u, _blocks)
- delete u;
+ // create a basic block given a range of instructions
+ template<typename Iterator>
+ Block *addBlock(Iterator first, Iterator last) {
+ Block* block = new Block;
+ _blocks.push_back(block);
+ copy(first, last, back_inserter(block->_instructions));
+ return block;
}
+ // create graph from a range of instructions
template<typename Iterator>
void addBlocksFromScript(Iterator scriptBegin, Iterator scriptEnd) {
Jump *jump;
@@ -78,224 +84,38 @@
foreach (Block *block, _blocks) {
if ((jump = dynamic_cast<Jump*>(block->_instructions.back())))
addEdge(block, _targets[jump->target()]);
- map<address_t, Block*>::iterator succ = next(_targets.find(block->_instructions.front()->_addr));
+ std::map<address_t, Block*>::iterator succ = next(_targets.find(block->_instructions.front()->_addr));
if (succ != _targets.end() && (!jump || dynamic_cast<CondJump*>(jump)))
addEdge(block, succ->second);
}
}
- void setEntry(address_t entry) {
- foreach (Block *block, _blocks)
- if (block->_instructions.front()->_addr == entry)
- _entry = block;
- }
+ void setEntry(address_t entry);
- template<typename Iterator>
- Block *addBlock(Iterator first, Iterator last) {
- Block* block = new Block;
- _blocks.push_back(block);
- copy(first, last, back_inserter(block->_instructions));
- return block;
- }
+ void loopStruct(); // fill in all information about loops
+ std::list<Block*> intervals(); // partition graph into intervals and return list of header blocks
- void addEdge(Block *from, Block *to) {
- from->_out.push_back(to);
- to->_in.push_back(from);
- }
+ void orderBlocks(); // assign block numbers in post-order
+ void removeJumpsToJumps();
+ void removeUnreachableBlocks(); // to be called after order blocks
- void removeJumpsToJumps() {
- for (bool changed = true; changed; ) {
- changed = false;
- foreach (Block *u, _blocks) {
- foreach (Block *v, u->_out) {
- Jump *jump = dynamic_cast<Jump*>(v->_instructions.front());
- if (jump && !dynamic_cast<CondJump*>(jump) && jump->target() != jump->_addr) {
- changed = true;
- replaceEdges(u, v, _targets[jump->target()]);
- }
- }
- }
- }
- }
+ std::string graphvizToString(const std::string &fontname="", int fontsize=0);
- void replaceEdges(Block *from, Block *oldTo, Block *newTo) {
- size_t n = count(oldTo->_in.begin(), oldTo->_in.end(), from);
- oldTo->_in.remove(from);
- fill_n(back_inserter(newTo->_in), n, from);
- foreach (Block *&block, from->_out)
- if (block == oldTo)
- block = newTo;
- }
- // to be called after order blocks
- void removeUnreachableBlocks() {
- foreach (Block *u, _blocks)
- if (!u->_number) {
- foreach (Block *v, u->_out)
- v->_in.remove(u);
- }
- for (list<Block*>::iterator it = _blocks.begin(); it != _blocks.end(); )
- if ((*it)->_number)
- it++;
- else {
- delete *it;
- it = _blocks.erase(it);
- }
- }
+private:
+ LoopType loopType(Block *head, Block *latch);
+ Block *loopFollow(Block *head, Block *latch); // to be called after loopType
+ bool inLoop(Block *head, Block *latch, Block *u);
- // assign block numbers in post-order
- void orderBlocks() {
- assert(_entry);
- orderVisit(_entry, 0);
- }
+ void addEdge(Block *from, Block *to);
- int orderVisit(Block *u, int number) {
- u->_number = -1;
- foreach (Block *v, u->_out)
- if (!v->_number)
- number = orderVisit(v, number);
- u->_number = ++number;
- return number;
- }
+ static std::string graphvizEscapeLabel(const std::string &s);
+ int orderVisit(Block *u, int number); // visit blocks recursively, depth first, helper for orderBlocks
- std::list<Block*> intervals() const {
- std::list<Block*> ret;
- assignIntervals();
- foreach (Block *u, _blocks)
- if (u->_interval == u)
- ret.push_back(u);
- return ret;
- }
+ void replaceEdges(Block *from, Block *oldTo, Block *newTo);
+ void assignIntervals(); // can be called multiple times
+ void extendIntervals();
- bool inLoop(Block *head, Block *latch, Block *u) {
- return u->_interval == head && latch->_number <= u->_number && u->_number < head->_number;
- }
-
- LoopType loopType(Block *head, Block *latch) {
- if (head->_out.size() == 1 && latch->_out.size() == 1)
- return ENDLESS;
- if (head->_out.size() == 1 && latch->_out.size() == 2)
- return POST_TESTED;
- if (head->_out.size() == 2 && latch->_out.size() == 1)
- return PRE_TESTED;
- // head->_out.size() == 2 && latch->_out.size() == 2
- if (inLoop(head, latch, head->_out.front()))
- return POST_TESTED;
- else
- return PRE_TESTED;
- }
-
- Block *loopFollow(Block *head, Block *latch) {
- if (head->_loopType == PRE_TESTED)
- return head->_out.front();
- if (head->_loopType == POST_TESTED)
- return latch->_out.back();
- // ENDLESS
- Block *ret = 0;
- foreach (Block *u, _blocks)
- if (inLoop(head, latch, u) && u->_out.size() == 2 && (!ret || ret->_number < u->_out.back()->_number))
- ret = u->_out.back();
- return ret;
- }
-
- void loopStruct() {
- for (size_t size = _blocks.size()+1; size > intervals().size(); size = intervals().size(), extendIntervals())
- foreach (Block *interval, intervals()) {
- foreach (Block *latch, interval->_in) {
- if (latch->_interval == interval && !latch->_loopHead) {
- foreach (Block *u, _blocks)
- if (inLoop(interval, latch, u))
- u->_loopHead = interval;
- interval->_loopLatch = latch; // TODO do we need this?
- interval->_loopType = loopType(interval, latch);
- interval->_loopFollow = loopFollow(interval, latch);
- }
- }
- }
- }
-
- void extendIntervals() {
- ControlFlowGraph d;
- std::map<Block*, Block*> trans;
- foreach (Block *interval, intervals()) {
- trans[interval] = d.addBlock(interval->_instructions.begin(), interval->_instructions.end());
- trans[interval]->_primitive = interval;
- }
- foreach (Block *interval, intervals())
- foreach (Block *u, interval->_in)
- if (u->_interval != interval)
- d.addEdge(trans[u->_interval], trans[interval]);
- d.setEntry(_entry->_instructions.front()->_addr);
- d.intervals();
- foreach (Block *du, d._blocks)
- foreach (Block *v, _blocks)
- if (v->_interval == du->_primitive)
- v->_interval = du->_interval->_primitive;
- }
-
- std::string graphvizToString(const std::string &fontname="", int fontsize=0) const {
- std::stringstream ret;
- ret << "digraph G {" << std::endl;
- foreach (Block *interval, intervals()) {
- ret << "subgraph " << '"' << "cluster_" << interval << '"' << " {" << std::endl;
- ret << "style=dotted;" << std::endl;
- foreach (Block *u, _blocks)
- if (u->_interval == interval) {
- ret << '"' << u << "\"[";
- if (fontname != "")
- ret << "fontname=" << '"' << fontname << "\",";
- if (fontsize != 0)
- ret << "fontsize=" << fontsize << ",";
- ret << "shape=box,label=\"<number: " << u->_number;
- if (u->_loopFollow)
- ret << ", loop_type=" << (u->_loopType == PRE_TESTED ? "pre_tested" : u->_loopType == POST_TESTED ? "post_tested" : "endless");
- ret << ">\\n" << graphvizEscapeLabel(u->toString()) << "\"];" << std::endl;
- }
- ret << "}" << std::endl;
- }
- foreach (Block *u, _blocks)
- foreach (Block *v, u->_out)
- ret << '"' << u << "\" -> \"" << v << '"' << (v == u->_loopFollow ? "[color=blue]" : "") << ";" << std::endl;
- ret << "}" << std::endl;
- return ret.str();
- }
-
- void assignIntervals() const {
- std::list<Block*> intervals;
- intervals.push_back(_entry);
- foreach (Block *interval, intervals) {
- interval->_interval = interval;
- for (bool added = true; added; ) {
- added = false;
- foreach (Block *m, _blocks) {
- bool allPredInInterval = true;
- foreach (Block *p, m->_in)
- allPredInInterval &= p->_interval == interval;
- if (!m->_interval && allPredInInterval) {
- added = true;
- m->_interval = interval;
- }
- }
- }
- foreach (Block *m, _blocks) {
- bool anyPredInInterval = false;
- foreach (Block *p, m->_in)
- anyPredInInterval |= p->_interval == interval;
- if (!m->_interval && anyPredInInterval)
- intervals.push_back(m);
- }
- }
- }
-
- static std::string graphvizEscapeLabel(const std::string &s) {
- std::string ret;
- foreach (char c, s) {
- if (c == '\n' || c == '"' || c == '\\')
- ret.push_back('\\');
- ret.push_back(c == '\n' ? 'l' : c); // align lines to the left
- }
- return ret;
- }
};
#endif
Modified: tools/branches/gsoc2009-decompiler/decompiler/instruction.h
===================================================================
--- tools/branches/gsoc2009-decompiler/decompiler/instruction.h 2009-07-01 17:13:46 UTC (rev 42002)
+++ tools/branches/gsoc2009-decompiler/decompiler/instruction.h 2009-07-01 17:18:54 UTC (rev 42003)
@@ -1,22 +1,24 @@
#ifndef INSTRUCTION_H
#define INSTRUCTION_H
+#include <cstdio>
+#include <sstream>
#include <string>
-#include <cstdio>
+#include <vector>
#include "misc.h"
struct Instruction {
- string _description;
+ std::string _description;
uint32 _addr;
- virtual string toString() {
- ostringstream ret;
- ret << phex(_addr-8) << " " << _description << endl;
+ virtual std::string toString() {
+ std::ostringstream ret;
+ ret << phex(_addr-8) << " " << _description << std::endl;
return ret.str();
}
- Instruction(string description, uint32 addr) : _description(description), _addr(addr) {
+ Instruction(std::string description, uint32 addr) : _description(description), _addr(addr) {
}
virtual ~Instruction() {
}
@@ -28,18 +30,18 @@
uint32 target() {
return _addr+_offset;
}
- string toString() {
- ostringstream ret;
- ret << phex(_addr-8) << " " << _description << " (" << phex(target()-8) << ")" << endl;
+ std::string toString() {
+ std::ostringstream ret;
+ ret << phex(_addr-8) << " " << _description << " (" << phex(target()-8) << ")" << std::endl;
return ret.str();
}
- Jump(string description, uint32 addr, int16 offset) : Instruction(description, addr), _offset(offset) {
+ Jump(std::string description, uint32 addr, int16 offset) : Instruction(description, addr), _offset(offset) {
}
};
struct CondJump : public Jump {
- CondJump(string description, uint32 addr, int16 offset) : Jump(description, addr, offset) {
+ CondJump(std::string description, uint32 addr, int16 offset) : Jump(description, addr, offset) {
}
};
@@ -53,7 +55,7 @@
struct Script {
- vector<Instruction*> _instructions;
+ std::vector<Instruction*> _instructions;
Script(Parser *parser, const char *filename) {
parser->parseFile(this, filename);
Added: tools/branches/gsoc2009-decompiler/decompiler/misc.cpp
===================================================================
--- tools/branches/gsoc2009-decompiler/decompiler/misc.cpp (rev 0)
+++ tools/branches/gsoc2009-decompiler/decompiler/misc.cpp 2009-07-01 17:18:54 UTC (rev 42003)
@@ -0,0 +1,39 @@
+#include "misc.h"
+
+std::string phex(int i, int width) {
+ std::ostringstream ret;
+ ret << std::hex << std::setfill('0') << std::setw(width) << i;
+ return ret.str();
+}
+
+uint32 read_be_uint32(std::ifstream &f) {
+ uint32 ret = 0;
+ ret |= f.get() << 24;
+ ret |= f.get() << 16;
+ ret |= f.get() << 8;
+ ret |= f.get();
+ return ret;
+}
+
+uint32 read_le_uint32(std::ifstream &f) {
+ uint32 ret = 0;
+ ret |= f.get();
+ ret |= f.get() << 8;
+ ret |= f.get() << 16;
+ ret |= f.get() << 24;
+ return ret;
+}
+
+uint16 read_le_uint16(std::ifstream &f) {
+ int ret = 0;
+ ret |= f.get();
+ ret |= f.get() << 8;
+ return (uint16) ret;
+}
+
+int16 read_le_int16(std::ifstream &f) {
+ int ret = 0;
+ ret |= f.get();
+ ret |= f.get() << 8;
+ return (int16) ret;
+}
Property changes on: tools/branches/gsoc2009-decompiler/decompiler/misc.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:eol-style
+ native
Modified: tools/branches/gsoc2009-decompiler/decompiler/misc.h
===================================================================
--- tools/branches/gsoc2009-decompiler/decompiler/misc.h 2009-07-01 17:13:46 UTC (rev 42002)
+++ tools/branches/gsoc2009-decompiler/decompiler/misc.h 2009-07-01 17:18:54 UTC (rev 42003)
@@ -19,49 +19,16 @@
typedef unsigned uint32;
typedef uint32 address_t; // bytecode address
-typedef uint32 index_t; // instruction number in intermediate script
template<typename Container, typename Element>
bool contains(const Container &c, const Element &e) {
return c.find(e) != c.end();
}
-std::string phex(int i, int width=4) {
- std::ostringstream ret;
- ret << std::hex << std::setfill('0') << std::setw(width) << i;
- return ret.str();
-}
+std::string phex(int i, int width=4);
+uint32 read_be_uint32(std::ifstream &f);
+uint32 read_le_uint32(std::ifstream &f);
+uint16 read_le_uint16(std::ifstream &f);
+int16 read_le_int16(std::ifstream &f);
-uint32 read_be_uint32(std::ifstream &f) {
- uint32 ret = 0;
- ret |= f.get() << 24;
- ret |= f.get() << 16;
- ret |= f.get() << 8;
- ret |= f.get();
- return ret;
-}
-
-uint32 read_le_uint32(std::ifstream &f) {
- uint32 ret = 0;
- ret |= f.get();
- ret |= f.get() << 8;
- ret |= f.get() << 16;
- ret |= f.get() << 24;
- return ret;
-}
-
-uint16 read_le_uint16(std::ifstream &f) {
- int ret = 0;
- ret |= f.get();
- ret |= f.get() << 8;
- return (uint16) ret;
-}
-
-int16 read_le_int16(std::ifstream &f) {
- int ret = 0;
- ret |= f.get();
- ret |= f.get() << 8;
- return (int16) ret;
-}
-
#endif
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list