]> git.localhorst.tv Git - l2e.git/commitdiff
support for arrays containing (yet) undefined references
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 17 Mar 2013 18:48:40 +0000 (19:48 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Sun, 17 Mar 2013 18:48:40 +0000 (19:48 +0100)
src/loader/Compiler.cpp
src/loader/Interpreter.cpp
src/loader/Loader.cpp
src/loader/Loader.h
src/loader/ObjectFile.cpp
src/loader/ObjectFile.h
src/loader/ParsedSource.cpp
src/main.cpp

index 96c0cc1425b643a8068a7b5ff6c8e2ff3697069e..b2d23be9c5cb984ee969ae3402706fbe02cf6289 100644 (file)
@@ -194,6 +194,7 @@ void Compiler::PrepareExternal(
                const Interpreter::PostponedDefinition &def) {
        ext.nameOffset = addressMap[def.identifier.c_str()];
        ext.referenceOffset = addressMap[def.object] + (def.dest - def.object);
+       ext.typeId = def.type;
        ext.inlined = 0;
        if (def.inlined) ext.inlined |= 1;
        if (def.aggregate) ext.inlined |= 2;
@@ -258,6 +259,9 @@ void Compiler::RelocateArray(char *array, int size) {
        for (char *i = array, *end = array + size;
                        i < end; i += sizeof(void *)) {
                char **dest = reinterpret_cast<char **>(i);
+               if (!*dest) {
+                       continue;
+               }
                map<const void *, unsigned int>::const_iterator
                                entry(addressMap.find(*dest));
                if (entry == addressMap.end()) {
index ecbb076224e225bad82cd92017c4db9d5caa33fc..3cb0d452a755b4f36b0345912026564e310b395c 100644 (file)
@@ -337,6 +337,7 @@ void Interpreter::ReadObject(int typeId, int id, char *object, const PropertyLis
                                array.data = alloc.Alloc(array.size);
                                array.ref = fd.IsReferenced();
                                arrays.push_back(array);
+                               std::memset(array.data, 0, array.size);
                                char *iter = reinterpret_cast<char *>(array.data);
                                if (i->second->GetLiteral().GetType() == Literal::ARRAY_PROPS) {
                                        const vector<PropertyList *> &list(i->second->GetLiteral().GetPropertyLists());
index 961ec7cff6d315dec5537338fe08ba8cfc0b9450..ba5dcc066d2b6c941534eb1160f57ded7106b74a 100644 (file)
@@ -3,12 +3,15 @@
 #include <climits>
 #include <cstring>
 #include <fstream>
+#include <ostream>
 #include <stdexcept>
 #include <utility>
 #include <SDL_image.h>
 
+using std::endl;
 using std::make_pair;
 using std::map;
+using std::ostream;
 using std::string;
 using std::vector;
 
@@ -73,6 +76,34 @@ void Loader::Load(const std::string &filePath) {
                throw;
        }
        objectFiles.insert(make_pair(filePath, block));
+
+       if (objectFiles.size() > 1) {
+               for (std::vector<MissingExternal>::iterator
+                               i(unlinked.begin()); i != unlinked.end();) {
+                       std::map<string, LoadedExport>::const_iterator
+                                       found(exports.find(i->identifier));
+                       if (found != exports.end()) {
+                               LinkExternal(*i, found->second);
+                               i = unlinked.erase(i);
+                       } else {
+                               ++i;
+                       }
+               }
+       }
+}
+
+void Loader::LinkExternal(
+               const MissingExternal &ext,
+               const LoadedExport &exp) {
+       if (ext.typeId != exp.typeId) {
+               throw std::runtime_error("casting not implemented in loader");
+       }
+       const TypeDescription &td = TypeDescription::Get(ext.typeId);
+       if (ext.inlined) {
+               std::memcpy(ext.dest, exp.location, td.Size());
+       } else {
+               std::memcpy(ext.dest, &exp.location, sizeof(void *));
+       }
 }
 
 void Loader::LoadExports(char *src, Export *begin, Export *end) {
@@ -88,18 +119,24 @@ void Loader::LoadExports(char *src, Export *begin, Export *end) {
 void Loader::LoadExternals(char *src, External *begin, External *end) {
        for (External *i = begin; i < end; ++i) {
                string identifier(src + i->nameOffset);
+               char *dest = src + i->referenceOffset;
+
                map<string, LoadedExport>::const_iterator
                                exp(exports.find(identifier));
                if (exp == exports.end()) {
-                       throw std::runtime_error("undefined reference to "
-                                       + identifier);
-               }
-               const TypeDescription &td(TypeDescription::Get(exp->second.typeId));
-               char *dest = src + i->referenceOffset;
-               if (i->inlined) {
-                       std::memcpy(dest, exp->second.location, td.Size());
+                       MissingExternal m;
+                       m.identifier = identifier;
+                       m.dest = dest;
+                       m.typeId = i->typeId;
+                       m.inlined = i->inlined;
+                       unlinked.push_back(m);
                } else {
-                       std::memcpy(dest, &exp->second.location, sizeof(char *));
+                       const TypeDescription &td(TypeDescription::Get(exp->second.typeId));
+                       if (i->inlined) {
+                               std::memcpy(dest, exp->second.location, td.Size());
+                       } else {
+                               std::memcpy(dest, &exp->second.location, sizeof(char *));
+                       }
                }
        }
 }
@@ -204,4 +241,47 @@ void Loader::InitArrays(Array *begin, Array *end) {
        }
 }
 
+
+ostream &Loader::Dump(ostream &out) const {
+       out << "loaded objects" << endl;
+       out << "==============" << endl;
+
+       out << objectFiles.size() << " object files" << endl;
+       for (std::map<string, char *>::const_iterator
+                       i(objectFiles.begin()), end(objectFiles.end());
+                       i != end; ++i) {
+               out << " - " << i->first << endl;
+       }
+
+       out << exports.size() << " exports" << endl;
+       for (std::map<string, LoadedExport>::const_iterator
+                       i(exports.begin()), end(exports.end());
+                       i != end; ++i) {
+               const TypeDescription &td = TypeDescription::Get(i->second.typeId);
+               out << " - " << td.TypeName() << ' ' << i->first << endl;
+       }
+
+       out << images.size() << " images" << endl;
+       for (std::map<string, SDL_Surface *>::const_iterator
+                       i(images.begin()), end(images.end());
+                       i != end; ++i) {
+               out << " - " << i->first << endl;
+       }
+
+       out << unlinked.size() << " missing objects" << endl;
+       for (std::vector<MissingExternal>::const_iterator
+                       i(unlinked.begin()), end(unlinked.end());
+                       i != end; ++i) {
+               const TypeDescription &td = TypeDescription::Get(
+                               i->typeId);
+               out << " - " << td.TypeName() << ' ';
+               if (!i->inlined) {
+                       out << '*';
+               }
+               out << i->identifier << endl;
+       }
+
+       return out;
+}
+
 }
index 50876384d744b26e617cd8982a1ee282153b24c7..c962f206119a9b67f22d11d52b9b58b806004b2e 100644 (file)
@@ -4,8 +4,10 @@
 #include "ObjectFile.h"
 #include "TypeDescription.h"
 
+#include <iosfwd>
 #include <map>
 #include <string>
+#include <vector>
 #include <SDL.h>
 
 namespace loader {
@@ -21,6 +23,8 @@ public:
 
        const std::map<std::string, LoadedExport> &Exports() const { return exports; }
 
+       std::ostream &Dump(std::ostream &) const;
+
 private:
        void LoadExports(char *src, Export *begin, Export *end);
        void LoadExternals(char *src, External *begin, External *end);
@@ -33,12 +37,31 @@ private:
        void InitObject(char *object, const TypeDescription &);
        void InitArrays(Array *begin, Array *end);
 
+       struct MissingExternal {
+               std::string identifier;
+               char *dest;
+               int typeId;
+               bool inlined;
+       };
+       void LinkExternal(const MissingExternal &, const LoadedExport &);
+
 private:
        std::map<std::string, char *> objectFiles;
        std::map<std::string, LoadedExport> exports;
        std::map<std::string, SDL_Surface *> images;
+       std::vector<MissingExternal> unlinked;
 
 };
 
 }
+
+
+namespace std {
+
+inline ostream &operator <<(ostream &o, const loader::Loader &l) {
+       return l.Dump(o);
+}
+
+}
+
 #endif
index 7207eb0ed92eb66e52d252f605cb5e75c97d63be..b6ab2b71c57e3724a93b0a5d987ad6ccf9fc1f32 100644 (file)
@@ -64,7 +64,7 @@ bool ObjectFileHeader::CheckSection(
                unsigned int end,
                unsigned int fsize) const {
        return begin >= sizeof(ObjectFileHeader)
-                       && begin < fsize
+                       && (begin < fsize || begin == end)
                        && end >= begin
                        && end <= fsize;
 }
index 98aff02918aaef733737fd2cc23765fd8f2d0ebc..56319a4dd444050681fb0aef7a8886893e91c3d6 100644 (file)
@@ -11,7 +11,7 @@ struct Export {
        /// Offset of the identifier in the file.
        unsigned int nameOffset;
        /// Type ID of referenced object.
-       unsigned int typeId;
+       int typeId;
        /// File-offset of the object's actual data.
        unsigned int dataOffset;
 };
@@ -22,9 +22,11 @@ struct External {
        unsigned int nameOffset;
        /// Target position for linking/inlining.
        unsigned int referenceOffset;
-       /// Nonzero if the object should be copied rather that
+       /// Target type.
+       int typeId;
+       /// True if the object should be copied rather that
        /// just writing a reference.
-       unsigned int inlined;
+       bool inlined;
 };
 
 struct Image {
@@ -36,16 +38,18 @@ struct Image {
 };
 
 struct Object {
-       unsigned int typeId;
+       int typeId;
        unsigned int size;
+
        char *RawObject();
        Object *Next();
 };
 
 struct Array {
-       unsigned int typeId;
+       int typeId;
        unsigned int size;
        bool ref;
+
        char *Data();
        Array *Next();
 };
index 90597475726663807fdc2beaa5b8f1d7fc627c98..422c5a0e31ce525bb0287f2870a76c493bd44e80 100644 (file)
@@ -527,7 +527,8 @@ const Literal *ScriptToken::GetLiteral() const {
 namespace std {
 
 ostream &operator <<(ostream &out, const loader::ParsedSource &source) {
-       out << "parsed source file" << endl;
+       out << "parsed sources" << endl;
+       out << "==============" << endl;
        out << "declared objects: " << endl;
        for (map<string, loader::Declaration *>::const_iterator i(source.Declarations().begin()), end(source.Declarations().end()); i != end; ++i) {
                out << " - " << i->first << " of type " << i->second->TypeName() << endl;
@@ -543,6 +544,7 @@ ostream &operator <<(ostream &out, const loader::ParsedSource &source) {
        for (set<string>::const_iterator i(source.Exports().begin()), end(source.Exports().end()); i != end; ++i) {
                out << " - " << *i << endl;
        }
+       out << endl;
        return out;
 }
 
index c01154e0368038757444a418c8cb19340802a64c..672c41bfa8fa5c01024b2a154f45c4346d6c2548 100644 (file)
@@ -189,7 +189,7 @@ int main(int argc, char **argv) {
                                return 0;
                        }
                        case Arguments::DUMP: {
-                               std::cout << source << std::endl;
+                               std::cout << source << ld << std::endl;
                                return 0;
                        }
                        case Arguments::SOURCE_WIKI: {