#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;
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) {
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 *));
+ }
}
}
}
}
}
+
+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;
+}
+
}
#include "ObjectFile.h"
#include "TypeDescription.h"
+#include <iosfwd>
#include <map>
#include <string>
+#include <vector>
#include <SDL.h>
namespace loader {
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);
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