]> git.localhorst.tv Git - l2e.git/blob - Compiler.cpp
5575838b83f9664bcb2c21ecbca6f47ec17d8465
[l2e.git] / Compiler.cpp
1 /*
2  * Compiler.cpp
3  *
4  *  Created on: Sep 11, 2012
5  *      Author: holy
6  */
7
8 #include "Compiler.h"
9
10 #include "Interpreter.h"
11
12 #include <climits>
13 #include <cstring>
14 #include <map>
15 #include <ostream>
16 #include <set>
17 #include <string>
18 #include <vector>
19
20 using std::map;
21 using std::ostream;
22 using std::set;
23 using std::string;
24 using std::vector;
25
26 namespace loader {
27
28 Compiler::Compiler(const Interpreter &intp)
29 : intp(intp)
30 , cursor(0) {
31         int headerSize(sizeof(ObjectFileHeader) + (intp.Values().size() * sizeof(TypeOffset)));
32
33         fileHeader.exportsBegin = headerSize + Remaining(headerSize, 16);
34         fileHeader.exportsEnd = fileHeader.exportsBegin + (intp.ExportedIdentifiers().size() * sizeof(Export));
35
36         fileHeader.externalsBegin = fileHeader.exportsEnd + Remaining(fileHeader.exportsEnd, 16);
37         fileHeader.externalsEnd = fileHeader.externalsBegin + (intp.PostponedDefinitions().size() * sizeof(External));
38
39         fileHeader.exportStringsBegin = fileHeader.externalsEnd + Remaining(fileHeader.externalsEnd, 16);
40         fileHeader.exportStringsEnd = fileHeader.exportStringsBegin;
41         for (set<string>::const_iterator i(intp.ExportedIdentifiers().begin()), end(intp.ExportedIdentifiers().end()); i != end; ++i) {
42                 fileHeader.exportStringsEnd += i->size() + 1;
43         }
44
45         fileHeader.externalStringsBegin = fileHeader.exportStringsEnd + Remaining(fileHeader.exportStringsEnd, 16);
46         fileHeader.externalStringsEnd = fileHeader.externalStringsBegin;
47         for(vector<Interpreter::PostponedDefinition>::const_iterator i(intp.PostponedDefinitions().begin()), end(intp.PostponedDefinitions().end()); i != end; ++i) {
48                 fileHeader.externalStringsEnd += std::strlen(i->identifier) + 1;
49         }
50
51         fileHeader.imagesBegin = fileHeader.externalStringsEnd + Remaining(fileHeader.externalStringsEnd, 16);
52         fileHeader.imagesEnd = fileHeader.imagesBegin + (intp.Images().size() * sizeof(ImageProperties));
53         for (map<string, SDL_Surface *>::const_iterator i(intp.Images().begin()), end(intp.Images().end()); i != end; ++i) {
54                 fileHeader.imagesEnd += i->second->w * i->second->h * i->second->format->BytesPerPixel;
55         }
56
57         fileHeader.objectsBegin = fileHeader.imagesEnd + Remaining(fileHeader.imagesEnd, 16);
58         fileHeader.objectsEnd = fileHeader.objectsBegin;
59         for (map<int, vector<void *> >::const_iterator i(intp.Values().begin()), end(intp.Values().end()); i != end; ++i) {
60                 const TypeDescription &td(TypeDescription::Get(i->first));
61                 objectOffsets[i->first] = fileHeader.objectsEnd;
62                 fileHeader.objectsEnd += td.Size() * i->second.size();
63                 fileHeader.objectsEnd += Remaining(fileHeader.objectsEnd, 16);
64         }
65 }
66
67 void Compiler::Write(ostream &out) {
68         WriteHeader(out);
69         Pad(out, 16);
70         WriteExports(out);
71         Pad(out, 16);
72         WriteExternals(out);
73         Pad(out, 16);
74         WriteExportStrings(out);
75         Pad(out, 16);
76         WriteExternalStrings(out);
77         Pad(out, 16);
78         WriteImages(out);
79         Pad(out, 16);
80         WriteObjects(out);
81 }
82
83
84 void Compiler::WriteHeader(ostream &out) {
85         Write(out, reinterpret_cast<const char *>(&fileHeader), sizeof(ObjectFileHeader));
86         for(map<int, vector<void *> >::const_iterator i(intp.Values().begin()), end(intp.Values().end()); i != end; ++i) {
87                 TypeOffset to;
88                 to.typeId = i->first;
89                 to.begin = GetTypeOffset(i->first);
90                 to.end = to.begin + (i->second.size() * TypeDescription::Get(i->first).Size());
91                 Write(out, reinterpret_cast<const char *>(&to), sizeof(TypeOffset));
92         }
93         TypeOffset to;
94         to.typeId = 0;
95         to.begin = 0;
96         to.end = 0;
97         Write(out, reinterpret_cast<const char *>(&to), sizeof(TypeOffset));
98 }
99
100 void Compiler::WriteExports(ostream &out) {
101         int nameOffset(fileHeader.externalStringsBegin);
102         for (set<string>::const_iterator i(intp.ExportedIdentifiers().begin()), end(intp.ExportedIdentifiers().end()); i != end; ++i) {
103                 const Interpreter::ParsedDefinition &dfn(intp.GetDefinition(*i));
104                 Export exp;
105                 exp.nameOffset = nameOffset;
106                 exp.typeId = dfn.type;
107                 exp.dataOffset = ObjectOffset(dfn.type, dfn.id);
108                 Write(out, reinterpret_cast<char *>(&exp), sizeof(Export));
109                 nameOffset += i->size() + 1;
110         }
111 }
112
113 void Compiler::WriteExternals(ostream &out) {
114         int nameOffset(fileHeader.exportStringsBegin);
115         for(vector<Interpreter::PostponedDefinition>::const_iterator i(intp.PostponedDefinitions().begin()), end(intp.PostponedDefinitions().end()); i != end; ++i) {
116                 External ext;
117                 ext.nameOffset = nameOffset;
118                 ext.referenceOffset = ReferenceOffset(i->type, i->id, i->offset);
119                 ext.inlined = i->inlined ? 1 : 0;
120                 Write(out, reinterpret_cast<char *>(&ext), sizeof(External));
121                 nameOffset += std::strlen(i->identifier) + 1;
122         }
123 }
124
125 void Compiler::WriteExportStrings(ostream &out) {
126         for (set<string>::const_iterator i(intp.ExportedIdentifiers().begin()), end(intp.ExportedIdentifiers().end()); i != end; ++i) {
127                 Write(out, i->c_str(), i->size() + 1);
128         }
129 }
130
131 void Compiler::WriteExternalStrings(ostream &out) {
132         for(vector<Interpreter::PostponedDefinition>::const_iterator i(intp.PostponedDefinitions().begin()), end(intp.PostponedDefinitions().end()); i != end; ++i) {
133                 Write(out, i->identifier, std::strlen(i->identifier) + 1);
134         }
135 }
136
137 void Compiler::WriteImages(ostream &out) {
138         for (map<string, SDL_Surface *>::const_iterator i(intp.Images().begin()), end(intp.Images().end()); i != end; ++i) {
139                 ImageProperties ip;
140                 ip.flags = i->second->flags;
141                 ip.width = i->second->w;
142                 ip.height = i->second->h;
143                 ip.depth = i->second->format->BitsPerPixel;
144                 ip.pitch = i->second->pitch;
145                 ip.rmask = i->second->format->Rmask;
146                 ip.gmask = i->second->format->Gmask;
147                 ip.bmask = i->second->format->Bmask;
148                 ip.amask = i->second->format->Amask;
149                 Write(out, reinterpret_cast<char *>(&ip), sizeof(ImageProperties));
150                 SDL_LockSurface(i->second);
151                 Write(out, reinterpret_cast<char *>(i->second->pixels), ip.width * ip.height * (ip.depth / CHAR_BIT + (ip.depth % CHAR_BIT ? 1 : 0)));
152                 // TODO: store palette too?
153                 SDL_UnlockSurface(i->second);
154         }
155 }
156
157 void Compiler::WriteObjects(ostream &out) {
158         for (map<int, vector<void *> >::const_iterator i(intp.Values().begin()), end(intp.Values().end()); i != end; ++i) {
159                 const TypeDescription &td(TypeDescription::Get(i->first));
160                 for (vector<void *>::const_iterator j(i->second.begin()), jend(i->second.end()); j != jend; ++j) {
161                         Write(out, reinterpret_cast<char *>(*j), td.Size());
162                 }
163                 Pad(out, 16);
164         }
165 }
166
167
168 void Compiler::Write(ostream &out, const char *data, int amount) {
169         out.write(data, amount);
170         cursor += amount;
171 }
172
173 void Compiler::Pad(ostream &out, int to) {
174         for (int remaining(Remaining(cursor, to)); remaining > 0; --remaining) {
175                 out.put(0);
176                 ++cursor;
177         }
178 }
179
180 int Compiler::Remaining(int value, int alignment) {
181         int have(value % alignment);
182         return (have > 0) ? (16 - have) : 0;
183 }
184
185
186 int Compiler::ReferenceOffset(int typeId, int objectId, std::ptrdiff_t fieldOffset) const {
187         return ObjectOffset(typeId, objectId) + fieldOffset;
188 }
189
190 int Compiler::ObjectOffset(int typeId, int objectId) const {
191         const TypeDescription &td(TypeDescription::Get(typeId));
192         return GetTypeOffset(typeId) + (td.Size() * objectId);
193 }
194
195 int Compiler::GetTypeOffset(int typeId) const {
196         return objectOffsets.at(typeId);
197 }
198
199 }