]> git.localhorst.tv Git - l2e.git/commitdiff
added Compiler to turn an interpretation into an object file
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Thu, 13 Sep 2012 20:35:18 +0000 (22:35 +0200)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 24 Feb 2013 21:33:56 +0000 (22:33 +0100)
src/loader/Compiler.cpp [new file with mode: 0644]
src/loader/Compiler.h [new file with mode: 0644]

diff --git a/src/loader/Compiler.cpp b/src/loader/Compiler.cpp
new file mode 100644 (file)
index 0000000..59bebfb
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Compiler.cpp
+ *
+ *  Created on: Sep 11, 2012
+ *      Author: holy
+ */
+
+#include "Compiler.h"
+
+#include "Interpreter.h"
+
+#include <cstring>
+#include <map>
+#include <ostream>
+#include <set>
+#include <string>
+#include <vector>
+
+using std::map;
+using std::ostream;
+using std::set;
+using std::string;
+using std::vector;
+
+namespace loader {
+
+Compiler::Compiler(const Interpreter &intp)
+: intp(intp)
+, cursor(0) {
+       int headerSize(4 + (5 * sizeof(int)) + (intp.Values().size() * 2 * sizeof(int)));
+
+       exportsOffset = headerSize + Remaining(headerSize, 16);
+       int exportsSize(intp.ExportedIdentifiers().size() * sizeof(Export));
+
+       externalsOffset = exportsOffset + exportsSize + Remaining(exportsSize, 16);
+       int externalsSize(intp.PostponedDefinitions().size() * sizeof(External));
+
+       exportStringsOffset = externalsOffset + externalsSize + Remaining(externalsSize, 16);
+       int exportStringsSize(0);
+       for (set<string>::const_iterator i(intp.ExportedIdentifiers().begin()), end(intp.ExportedIdentifiers().end()); i != end; ++i) {
+               exportStringsSize += i->size() + 1;
+       }
+
+       externalStringsOffset = exportStringsOffset + exportStringsSize + Remaining(exportStringsSize, 16);
+       int externalStringsSize(0);
+       for(vector<Interpreter::PostponedDefinition>::const_iterator i(intp.PostponedDefinitions().begin()), end(intp.PostponedDefinitions().end()); i != end; ++i) {
+               externalStringsSize += std::strlen(i->identifier) + 1;
+       }
+
+       imagesOffset = externalStringsOffset + externalStringsSize + Remaining(externalStringsSize, 16);
+       int imagesSize(intp.Images().size() * sizeof(ImageProperties));
+       for (map<string, SDL_Surface *>::const_iterator i(intp.Images().begin()), end(intp.Images().end()); i != end; ++i) {
+               imagesSize += i->second->w * i->second->h * i->second->format->BytesPerPixel;
+       }
+
+       objectsOffset = imagesOffset + imagesSize + Remaining(imagesSize, 16);
+       int objectsSize(0);
+       for (map<int, vector<void *> >::const_iterator i(intp.Values().begin()), end(intp.Values().end()); i != end; ++i) {
+               const TypeDescription &td(TypeDescription::Get(i->first));
+               objectOffsets[i->first] = objectsOffset + objectsSize;
+               objectsSize += td.Size() * i->second.size();
+               objectsSize += Remaining(objectsSize, 16);
+       }
+}
+
+void Compiler::Write(ostream &out) {
+       WriteHeader(out);
+       Pad(out, 16);
+       WriteExports(out);
+       Pad(out, 16);
+       WriteExternals(out);
+       Pad(out, 16);
+       WriteExportStrings(out);
+       Pad(out, 16);
+       WriteExternalStrings(out);
+       Pad(out, 16);
+       WriteImages(out);
+       Pad(out, 16);
+       WriteObjects(out);
+}
+
+
+void Compiler::WriteHeader(ostream &out) {
+       Write(out, "L2O\n", 4);
+       Write(out, reinterpret_cast<const char *>(&exportsOffset), sizeof(int));
+       Write(out, reinterpret_cast<const char *>(&externalsOffset), sizeof(int));
+       Write(out, reinterpret_cast<const char *>(&externalStringsOffset), sizeof(int));
+       Write(out, reinterpret_cast<const char *>(&exportStringsOffset), sizeof(int));
+       Write(out, reinterpret_cast<const char *>(&imagesOffset), sizeof(int));
+       Write(out, reinterpret_cast<const char *>(&objectsOffset), sizeof(int));
+       for(map<int, vector<void *> >::const_iterator i(intp.Values().begin()), end(intp.Values().end()); i != end; ++i) {
+               Write(out, reinterpret_cast<const char *>(&i->first), sizeof(int));
+               int typeOffset(TypeOffset(i->first));
+               Write(out, reinterpret_cast<const char *>(&typeOffset), sizeof(int));
+       }
+}
+
+void Compiler::WriteExports(ostream &out) {
+       int nameOffset(externalStringsOffset);
+       for (set<string>::const_iterator i(intp.ExportedIdentifiers().begin()), end(intp.ExportedIdentifiers().end()); i != end; ++i) {
+               const Interpreter::ParsedDefinition &dfn(intp.GetDefinition(*i));
+               Export exp;
+               exp.nameOffset = nameOffset;
+               exp.typeId = dfn.type;
+               exp.dataOffset = ObjectOffset(dfn.type, dfn.id);
+               Write(out, reinterpret_cast<char *>(&exp), sizeof(Export));
+               nameOffset += i->size() + 1;
+       }
+}
+
+void Compiler::WriteExternals(ostream &out) {
+       int nameOffset(exportStringsOffset);
+       for(vector<Interpreter::PostponedDefinition>::const_iterator i(intp.PostponedDefinitions().begin()), end(intp.PostponedDefinitions().end()); i != end; ++i) {
+               External ext;
+               ext.nameOffset = nameOffset;
+               ext.referenceOffset = ReferenceOffset(i->type, i->id, i->offset);
+               ext.inlined = i->inlined ? 1 : 0;
+               Write(out, reinterpret_cast<char *>(&ext), sizeof(External));
+               nameOffset += std::strlen(i->identifier) + 1;
+       }
+}
+
+void Compiler::WriteExportStrings(ostream &out) {
+       for (set<string>::const_iterator i(intp.ExportedIdentifiers().begin()), end(intp.ExportedIdentifiers().end()); i != end; ++i) {
+               Write(out, i->c_str(), i->size() + 1);
+       }
+}
+
+void Compiler::WriteExternalStrings(ostream &out) {
+       for(vector<Interpreter::PostponedDefinition>::const_iterator i(intp.PostponedDefinitions().begin()), end(intp.PostponedDefinitions().end()); i != end; ++i) {
+               Write(out, i->identifier, std::strlen(i->identifier) + 1);
+       }
+}
+
+void Compiler::WriteImages(ostream &out) {
+       for (map<string, SDL_Surface *>::const_iterator i(intp.Images().begin()), end(intp.Images().end()); i != end; ++i) {
+               ImageProperties ip;
+               ip.flags = i->second->flags;
+               ip.width = i->second->w;
+               ip.height = i->second->h;
+               ip.depth = i->second->format->BitsPerPixel;
+               ip.rmask = i->second->format->Rmask;
+               ip.gmask = i->second->format->Gmask;
+               ip.bmask = i->second->format->Bmask;
+               ip.amask = i->second->format->Amask;
+               Write(out, reinterpret_cast<char *>(&ip), sizeof(ImageProperties));
+               SDL_LockSurface(i->second);
+               Write(out, reinterpret_cast<char *>(i->second->pixels), ip.width * ip.height * i->second->format->BytesPerPixel);
+               // TODO: store palette too?
+               SDL_UnlockSurface(i->second);
+       }
+}
+
+void Compiler::WriteObjects(ostream &out) {
+       for (map<int, vector<void *> >::const_iterator i(intp.Values().begin()), end(intp.Values().end()); i != end; ++i) {
+               const TypeDescription &td(TypeDescription::Get(i->first));
+               for (vector<void *>::const_iterator j(i->second.begin()), jend(i->second.end()); j != jend; ++j) {
+                       Write(out, reinterpret_cast<char *>(*j), td.Size());
+               }
+               Pad(out, 16);
+       }
+}
+
+
+void Compiler::Write(ostream &out, const char *data, int amount) {
+       out.write(data, amount);
+       cursor += amount;
+}
+
+void Compiler::Pad(ostream &out, int to) {
+       for (int remaining(Remaining(cursor, to)); remaining > 0; --remaining) {
+               out.put(0);
+               ++cursor;
+       }
+}
+
+int Compiler::Remaining(int value, int alignment) {
+       int have(value % alignment);
+       return (have > 0) ? (16 - have) : 0;
+}
+
+
+int Compiler::ReferenceOffset(int typeId, int objectId, std::ptrdiff_t fieldOffset) const {
+       return ObjectOffset(typeId, objectId) + fieldOffset;
+}
+
+int Compiler::ObjectOffset(int typeId, int objectId) const {
+       const TypeDescription &td(TypeDescription::Get(typeId));
+       return TypeOffset(typeId) + (td.Size() * objectId);
+}
+
+int Compiler::TypeOffset(int typeId) const {
+       return objectOffsets.at(typeId);
+}
+
+}
diff --git a/src/loader/Compiler.h b/src/loader/Compiler.h
new file mode 100644 (file)
index 0000000..d2f0361
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Compiler.h
+ *
+ *  Created on: Sep 11, 2012
+ *      Author: holy
+ */
+
+#ifndef LOADER_COMPILER_H_
+#define LOADER_COMPILER_H_
+
+#include <iosfwd>
+#include <map>
+#include <memory>
+#include <SDL.h>
+
+namespace loader {
+
+class Interpreter;
+
+class Compiler {
+
+public:
+       explicit Compiler(const Interpreter &intp);
+       ~Compiler() { }
+private:
+       Compiler(const Compiler &);
+       Compiler &operator =(const Compiler &);
+
+public:
+       void Write(std::ostream &);
+
+       struct Export {
+               int nameOffset;
+               int typeId;
+               int dataOffset;
+       };
+
+       struct External {
+               int nameOffset;
+               int referenceOffset;
+               int inlined;
+       };
+
+       struct ImageProperties {
+               Uint32 flags;
+               int width;
+               int height;
+               int depth;
+               Uint32 rmask;
+               Uint32 gmask;
+               Uint32 bmask;
+               Uint32 amask;
+       };
+
+private:
+       void WriteHeader(std::ostream &);
+       void WriteExports(std::ostream &);
+       void WriteExternals(std::ostream &);
+       void WriteExportStrings(std::ostream &);
+       void WriteExternalStrings(std::ostream &);
+       void WriteImages(std::ostream &);
+       void WriteObjects(std::ostream &);
+
+       void Write(std::ostream &, const char *data, int amount);
+       void Pad(std::ostream &, int to);
+       static int Remaining(int value, int alignment);
+
+       int ReferenceOffset(int typeId, int objectId, std::ptrdiff_t fieldOffset) const;
+       int ObjectOffset(int typeId, int objectId) const;
+       int TypeOffset(int typeId) const;
+
+private:
+       const Interpreter &intp;
+
+       int cursor;
+
+       int exportsOffset;
+       int externalsOffset;
+       int externalStringsOffset;
+       int exportStringsOffset;
+       int imagesOffset;
+       int objectsOffset;
+
+       std::map<int, int> objectOffsets;
+
+};
+
+}
+
+#endif /* LOADER_COMPILER_H_ */