-/*
- * Compiler.cpp
- *
- * Created on: Sep 11, 2012
- * Author: holy
- */
-
#include "Compiler.h"
#include "Interpreter.h"
+#include "TypeDescription.h"
#include <climits>
#include <cstring>
+#include <iostream>
#include <map>
#include <ostream>
#include <set>
+#include <stdexcept>
#include <string>
+#include <utility>
#include <vector>
+using std::iostream;
+using std::make_pair;
using std::map;
using std::ostream;
+using std::runtime_error;
using std::set;
using std::string;
+using std::strlen;
using std::vector;
namespace loader {
Compiler::Compiler(const Interpreter &intp)
: intp(intp)
, cursor(0) {
- int headerSize(sizeof(ObjectFileHeader) + (intp.Values().size() * sizeof(TypeOffset)));
-
- fileHeader.exportsBegin = headerSize + Remaining(headerSize, 16);
- fileHeader.exportsEnd = fileHeader.exportsBegin + (intp.ExportedIdentifiers().size() * sizeof(Export));
+ int headerSize(sizeof(ObjectFileHeader));
- fileHeader.externalsBegin = fileHeader.exportsEnd + Remaining(fileHeader.exportsEnd, 16);
- fileHeader.externalsEnd = fileHeader.externalsBegin + (intp.PostponedDefinitions().size() * sizeof(External));
-
- fileHeader.exportStringsBegin = fileHeader.externalsEnd + Remaining(fileHeader.externalsEnd, 16);
- fileHeader.exportStringsEnd = fileHeader.exportStringsBegin;
- for (set<string>::const_iterator i(intp.ExportedIdentifiers().begin()), end(intp.ExportedIdentifiers().end()); i != end; ++i) {
- fileHeader.exportStringsEnd += i->size() + 1;
- }
+ fileHeader.exportsBegin = headerSize;
+ fileHeader.exportsEnd = fileHeader.exportsBegin
+ + (intp.ExportedIdentifiers().size() * sizeof(Export));
- fileHeader.externalStringsBegin = fileHeader.exportStringsEnd + Remaining(fileHeader.exportStringsEnd, 16);
- fileHeader.externalStringsEnd = fileHeader.externalStringsBegin;
- for(vector<Interpreter::PostponedDefinition>::const_iterator i(intp.PostponedDefinitions().begin()), end(intp.PostponedDefinitions().end()); i != end; ++i) {
- fileHeader.externalStringsEnd += std::strlen(i->identifier) + 1;
- }
-
- fileHeader.imagesBegin = fileHeader.externalStringsEnd + Remaining(fileHeader.externalStringsEnd, 16);
- fileHeader.imagesEnd = fileHeader.imagesBegin + (intp.Images().size() * sizeof(ImageProperties));
- for (map<string, SDL_Surface *>::const_iterator i(intp.Images().begin()), end(intp.Images().end()); i != end; ++i) {
- fileHeader.imagesEnd += i->second->w * i->second->h * i->second->format->BytesPerPixel;
- }
+ fileHeader.externalsBegin = fileHeader.exportsEnd;
+ fileHeader.externalsEnd = fileHeader.externalsBegin
+ + (intp.PostponedDefinitions().size() * sizeof(External));
- fileHeader.objectsBegin = fileHeader.imagesEnd + Remaining(fileHeader.imagesEnd, 16);
- fileHeader.objectsEnd = fileHeader.objectsBegin;
- 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] = fileHeader.objectsEnd;
- fileHeader.objectsEnd += td.Size() * i->second.size();
- fileHeader.objectsEnd += Remaining(fileHeader.objectsEnd, 16);
- }
+ fileHeader.objectsBegin = fileHeader.externalsEnd
+ + Remaining(fileHeader.externalsEnd, 16);
}
-void Compiler::Write(ostream &out) {
- WriteHeader(out);
+void Compiler::Write(iostream &out) {
+ ReserveHeader(out);
+ WriteObjects(out);
+ WriteOwnStrings(out);
+ fileHeader.objectsEnd = cursor;
Pad(out, 16);
+ fileHeader.arraysBegin = cursor;
+ WriteArrays(out);
+ fileHeader.arraysEnd = cursor;
+ out.seekp(0);
+ cursor = 0;
+ WriteHeader(out);
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);
+ out.seekg(fileHeader.objectsBegin);
+ out.clear();
+ Relocate(out);
}
+void Compiler::ReserveHeader(ostream &out) {
+ Fill(out, fileHeader.objectsBegin);
+}
void Compiler::WriteHeader(ostream &out) {
- Write(out, reinterpret_cast<const char *>(&fileHeader), sizeof(ObjectFileHeader));
- for(map<int, vector<void *> >::const_iterator i(intp.Values().begin()), end(intp.Values().end()); i != end; ++i) {
- TypeOffset to;
- to.typeId = i->first;
- to.begin = GetTypeOffset(i->first);
- to.end = to.begin + (i->second.size() * TypeDescription::Get(i->first).Size());
- Write(out, reinterpret_cast<const char *>(&to), sizeof(TypeOffset));
+ Write(out, &fileHeader, sizeof(ObjectFileHeader));
+}
+
+void Compiler::WriteOwnStrings(ostream &out) {
+ for (set<string>::const_iterator
+ i(intp.ExportedIdentifiers().begin()),
+ end(intp.ExportedIdentifiers().end());
+ i != end; ++i) {
+ addressMap.insert(make_pair(i->c_str(), cursor));
+ Object object;
+ object.typeId = Interpreter::STRING_ID;
+ object.size = i->size() + 1;
+ Write(out, &object, sizeof(Object));
+ Write(out, i->c_str(), object.size);
+ }
+ for(vector<Interpreter::PostponedDefinition>::const_iterator
+ i(intp.PostponedDefinitions().begin()),
+ end(intp.PostponedDefinitions().end());
+ i != end; ++i) {
+ addressMap.insert(make_pair(
+ i->identifier.c_str(), cursor));
+ Object object;
+ object.typeId = Interpreter::STRING_ID;
+ object.size = i->identifier.size() + 1;
+ Write(out, &object, sizeof(Object));
+ Write(out, i->identifier.c_str(), object.size);
}
- TypeOffset to;
- to.typeId = 0;
- to.begin = 0;
- to.end = 0;
- Write(out, reinterpret_cast<const char *>(&to), sizeof(TypeOffset));
}
void Compiler::WriteExports(ostream &out) {
- int nameOffset(fileHeader.externalStringsBegin);
- for (set<string>::const_iterator i(intp.ExportedIdentifiers().begin()), end(intp.ExportedIdentifiers().end()); i != end; ++i) {
- const Interpreter::ParsedDefinition &dfn(intp.GetDefinition(*i));
+ for (set<string>::const_iterator
+ i(intp.ExportedIdentifiers().begin()),
+ end(intp.ExportedIdentifiers().end());
+ i != end; ++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;
+ PrepareExport(exp, *i);
+ Write(out, &exp, sizeof(Export));
}
}
void Compiler::WriteExternals(ostream &out) {
- int nameOffset(fileHeader.exportStringsBegin);
- for(vector<Interpreter::PostponedDefinition>::const_iterator i(intp.PostponedDefinitions().begin()), end(intp.PostponedDefinitions().end()); i != end; ++i) {
+ 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;
+ PrepareExternal(ext, *i);
+ Write(out, &ext, sizeof(External));
}
}
-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::WriteObjects(ostream &out) {
+ Pad(out, 16);
+ 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) {
+ Object object;
+ PrepareObject(object, td, *j);
+ Write(out, &object, sizeof(Object));
+ Write(out, *j, object.size);
+ }
}
}
-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::WriteArrays(ostream &out) {
+ Pad(out, 16);
+ for (vector<Interpreter::Array>::const_iterator
+ i(intp.Arrays().begin()), end(intp.Arrays().end());
+ i != end; ++i) {
+ Array array;
+ array.size = i->size;
+ array.ref = i->ref;
+ Write(out, &array, sizeof(Array));
+ addressMap.insert(make_pair(i->data, cursor));
+ Write(out, i->data, array.size);
}
}
-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.pitch = i->second->pitch;
- 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 * (ip.depth / CHAR_BIT + (ip.depth % CHAR_BIT ? 1 : 0)));
- // TODO: store palette too?
- SDL_UnlockSurface(i->second);
+
+void Compiler::PrepareExport(Export &exp, const string &str) {
+ const Interpreter::ParsedDefinition &dfn
+ = intp.GetDefinition(str);
+ exp.nameOffset = addressMap[str.c_str()];
+ exp.typeId = dfn.type;
+ exp.dataOffset = addressMap[intp.GetObject(dfn.type, str)];
+}
+
+void Compiler::PrepareExternal(
+ External &ext,
+ const Interpreter::PostponedDefinition &def) {
+ ext.nameOffset = addressMap[def.identifier.c_str()];
+ ext.referenceOffset = addressMap[def.object] + (def.dest - def.object);
+ ext.inlined = 0;
+ if (def.inlined) ext.inlined |= 1;
+ if (def.aggregate) ext.inlined |= 2;
+}
+
+void Compiler::PrepareObject(
+ Object &object,
+ const TypeDescription &td,
+ void *data) {
+ addressMap.insert(make_pair(data, cursor + sizeof(Object)));
+ object.typeId = td.TypeId();
+ switch (td.TypeId()) {
+ case Interpreter::STRING_ID:
+ object.size = strlen(
+ reinterpret_cast<char *>(data)) + 1;
+ break;
+ default:
+ object.size = td.Size();
+ break;
}
}
-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());
+void Compiler::Relocate(iostream &out) {
+ int bufferSize = TypeDescription::GetMaxSize();
+ char *buffer = new char[bufferSize];
+ for (;out && out.tellg() < fileHeader.objectsEnd;) {
+ // 20785
+ Object object;
+ out.read(reinterpret_cast<char *>(&object), sizeof(Object));
+ const TypeDescription &td = TypeDescription::Get(object.typeId);
+ if (td.NeedsLinking()) {
+ out.seekg(object.size, iostream::cur);
+ continue;
+ }
+ unsigned int pos = out.tellg();
+ out.seekg(pos);
+ out.read(buffer, object.size);
+ Relocate(buffer, td);
+ out.seekp(pos);
+ out.write(buffer, object.size);
+ out.seekg(out.tellp());
+ }
+ delete[] buffer;
+ out.seekg(fileHeader.arraysBegin);
+ Array array;
+ for (; out && out.tellg() < fileHeader.arraysEnd;) {
+ out.read(reinterpret_cast<char *>(&array), sizeof(Array));
+ if (!array.ref) {
+ out.seekg(array.size);
+ continue;
}
- Pad(out, 16);
+ buffer = new char[array.size];
+ unsigned int pos = out.tellg();
+ out.seekg(pos);
+ out.read(buffer, array.size);
+ RelocateArray(buffer, array.size);
+ out.seekp(pos);
+ out.write(buffer, array.size);
+ out.seekg(out.tellp());
+ delete[] buffer;
}
}
+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);
+ map<const void *, unsigned int>::const_iterator
+ entry(addressMap.find(*dest));
+ if (entry == addressMap.end()) {
+ throw runtime_error("unable to relocate array member");
+ }
+ unsigned int destOffset = entry->second;
+ *dest = reinterpret_cast<char *>(destOffset);
+ }
+}
-void Compiler::Write(ostream &out, const char *data, int amount) {
- out.write(data, amount);
+void Compiler::Relocate(char *object, const TypeDescription &td) {
+ for (TypeDescription::FieldIterator
+ i(td.FieldsBegin()), end(td.FieldsEnd());
+ i != end; ++i) {
+ const FieldDescription &fd = i->second;
+ if (!fd.IsAggregate() && !fd.IsReferenced()) {
+ continue;
+ }
+ char **dest = reinterpret_cast<char **>(
+ object + fd.Offset());
+ if (!(*dest)) {
+ continue;
+ }
+ map<const void *, unsigned int>::const_iterator
+ entry(addressMap.find(*dest));
+ if (entry == addressMap.end()) {
+ throw runtime_error(string("unable to relocate field ")
+ + i->first + " in object of type " + td.TypeName());
+ }
+ unsigned int destOffset = entry->second;
+ *dest = reinterpret_cast<char *>(destOffset);
+ }
+}
+
+
+void Compiler::Write(ostream &out, const void *data, int amount) {
+ out.write(reinterpret_cast<const char *>(data), amount);
cursor += amount;
}
void Compiler::Pad(ostream &out, int to) {
- for (int remaining(Remaining(cursor, to)); remaining > 0; --remaining) {
- out.put(0);
+ Fill(out, Remaining(cursor, to));
+}
+
+void Compiler::Fill(ostream &out, int count, char c) {
+ for (int remaining(count); remaining > 0; --remaining) {
+ out.put(c);
++cursor;
}
}
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 GetTypeOffset(typeId) + (td.Size() * objectId);
-}
-
-int Compiler::GetTypeOffset(int typeId) const {
- return objectOffsets.at(typeId);
-}
-
}
-/*
- * Compiler.h
- *
- * Created on: Sep 11, 2012
- * Author: holy
- */
-
#ifndef LOADER_COMPILER_H_
#define LOADER_COMPILER_H_
+#include "Interpreter.h"
#include "ObjectFile.h"
+#include "TypeDescription.h"
#include <iosfwd>
#include <map>
namespace loader {
-class Interpreter;
-
class Compiler {
public:
Compiler &operator =(const Compiler &);
public:
- void Write(std::ostream &);
+ void Write(std::iostream &);
private:
+ void ReserveHeader(std::ostream &);
+ void WriteObjects(std::ostream &);
+ void WriteOwnStrings(std::ostream &);
+ void WriteArrays(std::ostream &);
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 Relocate(std::iostream &);
+ void RelocateArray(char *, int size);
+ void Relocate(char *, const TypeDescription &);
+
+ void PrepareExport(Export &, const std::string &);
+ void PrepareExternal(External &, const Interpreter::PostponedDefinition &);
+ void PrepareObject(Object &, const TypeDescription &, void *);
+
+ void Write(std::ostream &, const void *data, int amount);
void Pad(std::ostream &, int to);
+ void Fill(std::ostream &, int count, char c = '\0');
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 GetTypeOffset(int typeId) const;
-
private:
const Interpreter &intp;
- int cursor;
+ unsigned int cursor;
ObjectFileHeader fileHeader;
- std::map<int, int> objectOffsets;
+ std::map<const void *, unsigned int> addressMap;
};
}
-#endif /* LOADER_COMPILER_H_ */
+#endif
}
}
+const Interpreter::ParsedDefinition &Interpreter::GetDefinition(const string &identifier) const {
+ std::map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(identifier));
+ if (i != parsedDefinitions.end()) {
+ return i->second;
+ } else {
+ throw Error("access to undefined object " + identifier);
+ }
+}
+
-void *Interpreter::GetObject(int typeId, const std::string &name) {
- std::map<string, ParsedDefinition>::const_iterator i(parsedDefinitions.find(name));
+void *Interpreter::GetObject(
+ int typeId,
+ const std::string &name) {
+ std::map<string, ParsedDefinition>::const_iterator
+ i(parsedDefinitions.find(name));
if (i != parsedDefinitions.end()) {
- const TypeDescription &requested(TypeDescription::Get(typeId));
- const TypeDescription &actual(TypeDescription::Get(i->second.type));
+ const TypeDescription &requested =
+ TypeDescription::Get(typeId);
+ const TypeDescription &actual =
+ TypeDescription::Get(i->second.type);
if (requested.TypeId() == actual.TypeId()) {
return values[actual.TypeId()][i->second.id];
} else if (actual.IsSubtypeOf(requested)) {
- char *sub(reinterpret_cast<char *>(values[actual.TypeId()][i->second.id]));
- std::ptrdiff_t offset(actual.SupertypeOffset(requested));
+ char *sub = reinterpret_cast<char *>(
+ values[actual.TypeId()][i->second.id]);
+ std::ptrdiff_t offset =
+ actual.SupertypeOffset(requested);
+ return sub - offset;
+ } else {
+ throw Error("cannot cast " + actual.TypeName()
+ + " to " + requested.TypeName());
+ }
+ } else {
+ throw Error("access to undefined object " + name);
+ }
+}
+
+const void *Interpreter::GetObject(
+ int typeId,
+ const std::string &name) const {
+ std::map<string, ParsedDefinition>::const_iterator
+ i(parsedDefinitions.find(name));
+ if (i != parsedDefinitions.end()) {
+ const TypeDescription &requested =
+ TypeDescription::Get(typeId);
+ const TypeDescription &actual =
+ TypeDescription::Get(i->second.type);
+ if (requested.TypeId() == actual.TypeId()) {
+ return values.at(actual.TypeId()).at(i->second.id);
+ } else if (actual.IsSubtypeOf(requested)) {
+ char *sub = reinterpret_cast<char *>(
+ values.at(actual.TypeId()).at(i->second.id));
+ std::ptrdiff_t offset =
+ actual.SupertypeOffset(requested);
return sub - offset;
} else {
- throw Error("cannot cast " + actual.TypeName() + " to " + requested.TypeName());
+ throw Error("cannot cast " + actual.TypeName()
+ + " to " + requested.TypeName());
}
} else {
throw Error("access to undefined object " + name);
if (fd.IsAggregate()) {
int arraySize(i->second->GetLiteral().ArraySize());
size_t memberSize = fd.IsReferenced() ? sizeof(char *) : fieldType.Size();
- char *aggregate = alloc.Alloc(arraySize * memberSize);
- char *iter = aggregate;
+ Array array;
+ array.size = arraySize * memberSize;
+ array.data = alloc.Alloc(array.size);
+ array.ref = fd.IsReferenced();
+ arrays.push_back(array);
+ char *iter = reinterpret_cast<char *>(array.data);
if (i->second->GetLiteral().GetType() == Literal::ARRAY_PROPS) {
const vector<PropertyList *> &list(i->second->GetLiteral().GetPropertyLists());
- for (vector<PropertyList *>::const_iterator j(list.begin()), end(list.end());
+ for (vector<PropertyList *>::const_iterator
+ j(list.begin()), end(list.end());
j != end; ++j, iter += memberSize) {
char *member;
if (fd.IsReferenced()) {
*reinterpret_cast<void **>(iter)
= GetObject(fd.TypeId(), *j);
} else {
- Postpone(iter, *j, fd.TypeId(), false);
+ Postpone(reinterpret_cast<char *>(array.data),
+ iter, *j, fd.TypeId(), false);
}
}
}
- std::memcpy(dest, &aggregate, sizeof(char *));
+ std::memcpy(dest, &array.data, sizeof(char *));
dest += sizeof(char *);
std::memcpy(dest, &arraySize, sizeof(int));
} else if (i->second->IsLiteral() && !fd.IsReferenced()) {
}
}
} else {
- Postpone(object, i->second->GetIdentifier(), fd.TypeId(), !fd.IsReferenced(), fd.IsAggregate());
+ Postpone(object, object + fd.Offset(), i->second->GetIdentifier(), fd.TypeId(), !fd.IsReferenced(), fd.IsAggregate());
}
}
td.Load(object);
}
void Interpreter::Postpone(
+ char *object,
char *dest,
const std::string &identifier,
int type,
bool inlined,
bool aggregate) {
- char *str(alloc.Alloc(identifier.size() + 1));
- std::memcpy(str, identifier.c_str(), identifier.size());
- str[identifier.size()] = '\0';
postponedDefinitions.push_back(
- PostponedDefinition(dest, str, type, inlined, aggregate));
+ PostponedDefinition(object, dest, identifier, type, inlined, aggregate));
}
/// Error is thrown if the object is undefined or a cast
/// was unsuccessful.
void *GetObject(int typeId, const std::string &name);
+ const void *GetObject(int typeId, const std::string &name) const;
/// Register the type descriptions of builtin types.
/// This should be called before any interpretation (like
/// linked by its identifier.
struct PostponedDefinition {
PostponedDefinition(
+ char *object,
char *dest,
- const char *identifier,
+ const std::string &identifier,
int type,
bool inlined,
bool aggregate)
- : dest(dest)
+ : object(object)
+ , dest(dest)
, identifier(identifier)
, type(type)
, inlined(inlined)
, aggregate(aggregate) { }
+ char *object;
char *dest;
- const char *identifier;
+ std::string identifier;
int type;
bool inlined;
bool aggregate;
}
/// Get the object definition for given identifier.
const ParsedDefinition &GetDefinition(const std::string &identifier);
+ const ParsedDefinition &GetDefinition(const std::string &identifier) const;
/// Get all images reference by he source.
/// The returned map is indexed by filenames relative to
/// the source file and contains ready-to-blit surfaces.
const std::map<int, std::vector<void *> > &Values() const {
return values;
}
+ struct Array {
+ void *data;
+ unsigned int size;
+ bool ref;
+ };
+ const std::vector<Array> &Arrays() const {
+ return arrays;
+ }
private:
/// Interpret given definition.
bool CanLink(const Value &) const;
/// Defer linking of given object reference.
void Postpone(
+ char *object,
char *dest,
const std::string &identifier,
int type,
std::vector<PostponedDefinition> postponedDefinitions;
std::map<std::string, SDL_Surface *> imageCache;
std::map<int, std::vector<void *> > values;
+ std::vector<Array> arrays;
};
-/*
- * Loader.cpp
- *
- * Created on: Sep 13, 2012
- * Author: holy
- */
-
#include "Loader.h"
#include <climits>
namespace loader {
Loader::~Loader() {
- for(map<string, LoadedObjectFile>::const_iterator i(objectFiles.begin()), end(objectFiles.end()); i != end; ++i) {
- if (i->second.surfaceCount) {
- for (int j(0); j < i->second.surfaceCount; ++j) {
- SDL_FreeSurface(i->second.surfaces[j]);
- }
- delete[] i->second.surfaces;
- }
- delete[] i->second.allocPtr;
+ for(map<string, char *>::const_iterator
+ i(objectFiles.begin()), end(objectFiles.end());
+ i != end; ++i) {
+ delete[] i->second;
}
}
int fileLength(file.tellg());
int length(fileLength + 15);
- LoadedObjectFile &object(objectFiles[filePath]);
- object.allocPtr = new char[length];
+ char *block = new char[length];
+ ObjectFileHeader *header =
+ reinterpret_cast<ObjectFileHeader *>(block);
- if (reinterpret_cast<unsigned long>(object.allocPtr) % 16) {
- object.fileHeader = reinterpret_cast<ObjectFileHeader *>(object.allocPtr + (16 - (reinterpret_cast<unsigned long>(object.allocPtr) % 16)));
- } else {
- object.fileHeader = reinterpret_cast<ObjectFileHeader *>(object.allocPtr);
+ unsigned long padding =
+ reinterpret_cast<unsigned long>(block) % 16;
+ if (padding) {
+ header = reinterpret_cast<ObjectFileHeader *>(
+ block + (16 - padding));
}
file.seekg(0, std::ios::beg);
- file.read(reinterpret_cast<char *>(object.fileHeader), fileLength);
-
- if (object.fileHeader->versionId != FORMAT_ID) {
- throw std::runtime_error("mismatched version id of file " + filePath);
+ file.read(reinterpret_cast<char *>(header), fileLength);
+
+ try {
+ header->IntegrityCheck(fileLength);
+
+ LoadExports(header->ident,
+ header->ExportsBegin(),
+ header->ExportsEnd());
+ LoadExternals(header->ident,
+ header->ExternalsBegin(),
+ header->ExternalsEnd());
+ LoadObjects(header->ident,
+ header->ObjectsBegin(),
+ header->ObjectsEnd());
+ } catch (...) {
+ delete[] block;
+ throw;
}
-
- LoadHeader(object);
- LoadExports(object);
- LoadImages(object);
- LinkObjects(object);
- LinkExternals(object);
+ objectFiles.insert(make_pair(filePath, block));
}
-void Loader::LoadHeader(LoadedObjectFile &object) {
- ObjectFileHeader *header(object.fileHeader);
- char *charHeader(reinterpret_cast<char *>(header));
-
- object.typeOffsetsBegin = reinterpret_cast<TypeOffset *>(charHeader + sizeof(ObjectFileHeader));
- for (object.typeOffsetsEnd = object.typeOffsetsBegin; object.typeOffsetsEnd->begin != 0 && object.typeOffsetsEnd->end != 0; ++object.typeOffsetsEnd);
-
- object.exportsBegin = reinterpret_cast<Export *>(charHeader + header->exportsBegin);
- object.exportsEnd = reinterpret_cast<Export *>(charHeader + header->exportsEnd);
-
- object.externalsBegin = reinterpret_cast<External *>(charHeader + header->externalsBegin);
- object.externalsEnd = reinterpret_cast<External *>(charHeader + header->externalsEnd);
-
- object.exportStringsBegin = charHeader + header->exportStringsBegin;
- object.exportStringsEnd = charHeader + header->exportStringsEnd;
-
- object.externalStringsBegin = charHeader + header->externalStringsBegin;
- object.externalStringsEnd = charHeader + header->externalStringsEnd;
-
- object.imagesBegin = charHeader + header->imagesBegin;
- object.imagesEnd = charHeader + header->imagesEnd;
-
- object.objectsBegin = charHeader + header->objectsBegin;
- object.objectsEnd = charHeader + header->objectsEnd;
-}
-
-void Loader::LoadExports(LoadedObjectFile &object) {
- for (Export *i(object.exportsBegin); i != object.exportsEnd; ++i) {
- string identifier(object.At(i->nameOffset));
+void Loader::LoadExports(char *src, Export *begin, Export *end) {
+ for (Export *i = begin; i < end; ++i) {
+ string identifier(src + i->nameOffset);
LoadedExport &exp(exports[identifier]);
exp.typeId = i->typeId;
- exp.location = object.At(i->dataOffset);
+ exp.location = src + i->dataOffset;
}
}
-void Loader::LinkExternals(LoadedObjectFile &object) {
- for (External *i(object.externalsBegin); i != object.externalsEnd; ++i) {
- string identifier(object.At(i->nameOffset));
- map<string, LoadedExport>::const_iterator exp(exports.find(identifier));
+void Loader::LoadExternals(char *src, External *begin, External *end) {
+ for (External *i = begin; i < end; ++i) {
+ string identifier(src + i->nameOffset);
+ map<string, LoadedExport>::const_iterator
+ exp(exports.find(identifier));
if (exp == exports.end()) {
- throw std::runtime_error("undefined reference to " + identifier);
+ throw std::runtime_error("undefined reference to "
+ + identifier);
}
const TypeDescription &td(TypeDescription::Get(exp->second.typeId));
- char *dest(object.At(i->referenceOffset));
+ char *dest = src + i->referenceOffset;
if (i->inlined) {
std::memcpy(dest, exp->second.location, td.Size());
} else {
}
}
-void Loader::LoadImages(LoadedObjectFile &object) {
- for (char *i(object.imagesBegin); i != object.imagesEnd;) {
- ImageProperties *props(reinterpret_cast<ImageProperties *>(i));
- i += sizeof(ImageProperties) + props->width * props->height * (props->depth / CHAR_BIT + (props->depth % CHAR_BIT ? 1 : 0));
- ++object.surfaceCount;
- }
- if (object.surfaceCount == 0) return;
-
- object.surfaces = new SDL_Surface *[object.surfaceCount];
- int index(0);
- for (char *i(object.imagesBegin); i != object.imagesEnd;) {
- ImageProperties *props(reinterpret_cast<ImageProperties *>(i));
- i += sizeof(ImageProperties);
- SDL_Surface *image(SDL_CreateRGBSurfaceFrom(
- i,
- props->width,
- props->height,
- props->depth,
- props->pitch,
- props->rmask,
- props->gmask,
- props->bmask,
- props->amask));
- i += props->width * props->height * (props->depth / CHAR_BIT + (props->depth % CHAR_BIT ? 1 : 0));
- object.surfaces[index] = image;
- ++index;
- }
-}
-
-void Loader::LinkObjects(LoadedObjectFile &object) {
- for (TypeOffset *type(object.typeOffsetsBegin); type != object.typeOffsetsEnd; ++type) {
- const TypeDescription &td(TypeDescription::Get(type->typeId));
- for (int offset(type->begin); offset != type->end; offset += td.Size()) {
- LinkObject(object, td, object.At(offset));
+void Loader::LoadObjects(char *src, Object *begin, Object *end) {
+ for (Object *i = begin; i < end; i = i->Next()) {
+ const TypeDescription &td =
+ TypeDescription::Get(i->typeId);
+ if (td.NeedsLinking()) {
+ LoadObject(src, i->RawObject(), td);
}
}
}
-void Loader::LinkObject(LoadedObjectFile &file, const TypeDescription &td, char *object) {
- for (TypeDescription::FieldIterator i(td.FieldsBegin()), end(td.FieldsEnd()); i != end; ++i) {
- const FieldDescription &field(i->second);
- if (!field.IsReferenced()) continue;
+void Loader::LoadObject(char *src, char *object, const TypeDescription &td) {
+ for (TypeDescription::FieldIterator
+ i(td.FieldsBegin()), end(td.FieldsEnd());
+ i != end; ++i) {
+ const FieldDescription &field = i->second;
+ if (!field.IsReferenced() && !field.IsAggregate()) {
+ continue;
+ }
char **dest(reinterpret_cast<char **>(object + field.Offset()));
- *dest = file.At(*reinterpret_cast<int *>(*dest));
+ if (*dest) {
+ *dest = src + *reinterpret_cast<unsigned int *>(dest);
+ }
}
}
-/*
- * Loader.h
- *
- * Created on: Sep 13, 2012
- * Author: holy
- */
-
#ifndef LOADER_LOADER_H_
#define LOADER_LOADER_H_
#include "ObjectFile.h"
#include "TypeDescription.h"
-namespace loader {
-
#include <map>
#include <string>
-#include <vector>
+#include <SDL.h>
+
+namespace loader {
class Loader {
void Load(const std::string &file);
private:
- void LoadHeader(LoadedObjectFile &);
- void LoadExports(LoadedObjectFile &);
- void LinkExternals(LoadedObjectFile &);
- void LoadImages(LoadedObjectFile &);
- void LinkObjects(LoadedObjectFile &);
- void LinkObject(LoadedObjectFile &, const TypeDescription &, char *object);
+ void LoadExports(char *src, Export *begin, Export *end);
+ void LoadExternals(char *src, External *begin, External *end);
+ void LoadObjects(char *src, Object *begin, Object *end);
+ void LoadObject(char *src, char *dest, const TypeDescription &);
private:
- std::map<std::string, LoadedObjectFile> objectFiles;
+ std::map<std::string, char *> objectFiles;
std::map<std::string, LoadedExport> exports;
};
}
-#endif /* LOADER_LOADER_H_ */
+#endif
-/*
- * ObjectFile.cpp
- *
- * Created on: Sep 15, 2012
- * Author: holy
- */
-
#include "ObjectFile.h"
+#include <stdexcept>
+
+using std::runtime_error;
+
+
namespace loader {
ObjectFileHeader::ObjectFileHeader()
, exportsEnd(0)
, externalsBegin(0)
, externalsEnd(0)
-, exportStringsBegin(0)
-, exportStringsEnd(0)
-, externalStringsBegin(0)
-, externalStringsEnd(0)
-, imagesBegin(0)
-, imagesEnd(0)
, objectsBegin(0)
-, objectsEnd(0) {
+, objectsEnd(0)
+, arraysBegin(0)
+, arraysEnd(0) {
ident[0] = 'L';
ident[1] = '2';
ident[2] = 'E';
ident[3] = '\n';
}
-LoadedObjectFile::LoadedObjectFile()
-: allocPtr(0)
-, fileHeader(0)
-, typeOffsetsBegin(0)
-, typeOffsetsEnd(0)
-, exportsBegin(0)
-, exportsEnd(0)
-, externalsBegin(0)
-, externalsEnd(0)
-, exportStringsBegin(0)
-, exportStringsEnd(0)
-, externalStringsBegin(0)
-, externalStringsEnd(0)
-, imagesBegin(0)
-, imagesEnd(0)
-, objectsBegin(0)
-, objectsEnd(0)
-, surfaces(0)
-, surfaceCount(0) {
+void ObjectFileHeader::IntegrityCheck(unsigned int fsize) const {
+ if (ident[0] != 'L'
+ || ident[1] != '2'
+ || ident[2] != 'E'
+ || ident[3] != '\n') {
+ throw runtime_error("magic bytes mismatch");
+ }
+ if (versionId != FORMAT_ID) {
+ throw runtime_error("format ID mismatch");
+ }
+ if (exportsBegin < sizeof(ObjectFileHeader)
+ || exportsBegin > fsize) {
+ throw runtime_error("exports section out of bounds");
+ }
+ if (exportsEnd < exportsBegin
+ || exportsEnd > fsize
+ || (exportsEnd - exportsBegin) % sizeof(Export) != 0) {
+ throw runtime_error("bogus exports section end");
+ }
+ if (externalsBegin < sizeof(ObjectFileHeader)
+ || externalsBegin >= fsize) {
+ throw runtime_error("externals section out of bounds");
+ }
+ if (externalsEnd < externalsBegin
+ || externalsEnd > fsize
+ || (externalsEnd - externalsBegin) % sizeof(External) != 0) {
+ throw runtime_error("bogus externals section end");
+ }
+ if (objectsBegin < sizeof(ObjectFileHeader)
+ || objectsBegin >= fsize
+ || objectsEnd < objectsBegin
+ || objectsEnd > fsize) {
+ throw runtime_error("objects section out of bounds");
+ }
+ if (arraysBegin < sizeof(ObjectFileHeader)
+ || arraysBegin >= fsize
+ || arraysEnd < arraysBegin
+ || arraysEnd > fsize) {
+ throw runtime_error("arrays section out of bounds");
+ }
+}
+
+Export *ObjectFileHeader::ExportsBegin() {
+ char *data = reinterpret_cast<char *>(this);
+ return reinterpret_cast<Export *>(data + exportsBegin);
+}
+
+Export *ObjectFileHeader::ExportsEnd() {
+ char *data = reinterpret_cast<char *>(this);
+ return reinterpret_cast<Export *>(data + exportsEnd);
+}
+
+External *ObjectFileHeader::ExternalsBegin() {
+ char *data = reinterpret_cast<char *>(this);
+ return reinterpret_cast<External *>(data + externalsBegin);
+}
+
+External *ObjectFileHeader::ExternalsEnd() {
+ char *data = reinterpret_cast<char *>(this);
+ return reinterpret_cast<External *>(data + externalsEnd);
+}
+
+Object *ObjectFileHeader::ObjectsBegin() {
+ char *data = reinterpret_cast<char *>(this);
+ return reinterpret_cast<Object *>(data + objectsBegin);
+}
+
+Object *ObjectFileHeader::ObjectsEnd() {
+ char *data = reinterpret_cast<char *>(this);
+ return reinterpret_cast<Object *>(data + objectsEnd);
+}
+
+Array *ObjectFileHeader::ArraysBegin() {
+ char *data = reinterpret_cast<char *>(this);
+ return reinterpret_cast<Array *>(data + arraysBegin);
+}
+
+Array *ObjectFileHeader::ArraysEnd() {
+ char *data = reinterpret_cast<char *>(this);
+ return reinterpret_cast<Array *>(data + arraysEnd);
+}
+
+
+char *Object::RawObject() {
+ return reinterpret_cast<char *>(this) + sizeof(Object);
+}
+
+Object *Object::Next() {
+ return reinterpret_cast<Object *>(RawObject() + size);
+}
+
+
+char *Array::Data() {
+ return reinterpret_cast<char *>(this) + sizeof(Array);
+}
+Array *Array::Next() {
+ return reinterpret_cast<Array *>(Data() + size);
}
}
-/*
- * ObjectFile.h
- *
- * Created on: Sep 15, 2012
- * Author: holy
- */
-
#ifndef LOADER_OBJECTFILE_H_
#define LOADER_OBJECTFILE_H_
namespace loader {
-const int FORMAT_ID(1);
-
-struct ObjectFileHeader {
- char ident[4];
-
- int versionId;
-
- int exportsBegin;
- int exportsEnd;
-
- int externalsBegin;
- int externalsEnd;
-
- int exportStringsBegin;
- int exportStringsEnd;
-
- int externalStringsBegin;
- int externalStringsEnd;
-
- int imagesBegin;
- int imagesEnd;
-
- int objectsBegin;
- int objectsEnd;
-
- ObjectFileHeader();
-};
-
-struct TypeOffset {
- int typeId;
- int begin;
- int end;
-};
+const unsigned int FORMAT_ID = 2;
struct Export {
- int nameOffset;
- int typeId;
- int dataOffset;
+ /// Offset of the identifier in the file.
+ unsigned int nameOffset;
+ /// Type ID of referenced object.
+ unsigned int typeId;
+ /// File-offset of the object's actual data.
+ unsigned int dataOffset;
};
struct External {
- int nameOffset;
- int referenceOffset;
- int inlined;
+ /// File-relative offset of the referenced object's
+ /// identifier.
+ unsigned int nameOffset;
+ /// Target position for linking/inlining.
+ unsigned int referenceOffset;
+ /// Nonzero if the object should be copied rather that
+ /// just writing a reference.
+ unsigned int inlined;
};
-struct ImageProperties {
- Uint32 flags;
- int width;
- int height;
- int depth;
- int pitch;
- Uint32 rmask;
- Uint32 gmask;
- Uint32 bmask;
- Uint32 amask;
+struct Object {
+ unsigned int typeId;
+ unsigned int size;
+ char *RawObject();
+ Object *Next();
};
-struct LoadedObjectFile {
- char *allocPtr;
- ObjectFileHeader *fileHeader;
-
- TypeOffset *typeOffsetsBegin;
- TypeOffset *typeOffsetsEnd;
-
- Export *exportsBegin;
- Export *exportsEnd;
-
- External *externalsBegin;
- External *externalsEnd;
-
- char *exportStringsBegin;
- char *exportStringsEnd;
-
- char *externalStringsBegin;
- char *externalStringsEnd;
-
- char *imagesBegin;
- char *imagesEnd;
+struct Array {
+ unsigned int size;
+ bool ref;
+ char *Data();
+ Array *Next();
+};
- char *objectsBegin;
- char *objectsEnd;
+struct ObjectFileHeader {
+ /// Has to be "L2E\n"
+ char ident[4];
- SDL_Surface **surfaces;
- int surfaceCount;
+ /// Version ID of the object file format
+ /// For now it must match FORMAT_ID for the loader to be
+ /// able to read it.
+ /// Backwards compatibility might be implemented at some
+ /// point in the future, but don't bet on that ever
+ /// happening.
+ unsigned int versionId;
+
+ /// File-relative offsets of the export section's begin
+ /// and end respectively.
+ /// Exports are named and typed addresses within the
+ /// file. This is essentially an array of Export structs.
+ unsigned int exportsBegin;
+ unsigned int exportsEnd;
+
+ /// File-relative offsets of the externals section's
+ /// begin and end respectively.
+ /// Each external names an entity which must be linked in
+ /// for this object file to function properly. This is
+ /// essentially an array of External structs.
+ unsigned int externalsBegin;
+ unsigned int externalsEnd;
+
+ /// File-relative offsets of the objet section's begin
+ /// and end respectively.
+ /// Each object begins with its type ID followed by its
+ /// size and finally the raw object data.
+ /// All referecte type fields should contain either a
+ /// file-relative offset or zero to indicate a null
+ /// reference.
+ /// This can be sen as a linked list where the next
+ /// object for a node can be obtained by adding the size
+ /// of to int and the object to the current node's
+ /// address.
+ unsigned int objectsBegin;
+ unsigned int objectsEnd;
+
+ /// File-relative offsets of the array section's begin
+ /// and end respectively.
+ /// Each array consists of an unsigned integer indicating
+ /// its size followed by a boolean flag which is true if
+ /// the arrays consists of pointers followed by the data.
+ unsigned int arraysBegin;
+ unsigned int arraysEnd;
- LoadedObjectFile();
+ ObjectFileHeader();
- char *At(int offset) { return reinterpret_cast<char *>(fileHeader) + offset; }
+ /// Check if there are any problems with the file header.
+ /// Throws a std::runtime_error on failure.
+ void IntegrityCheck(unsigned int fileSize) const;
+ Export *ExportsBegin();
+ Export *ExportsEnd();
+ External *ExternalsBegin();
+ External *ExternalsEnd();
+ Object *ObjectsBegin();
+ Object *ObjectsEnd();
+ Array *ArraysBegin();
+ Array *ArraysEnd();
};
struct LoadedExport {
}
-#endif /* LOADER_OBJECTFILE_H_ */
+#endif
#include "PagedAllocator.h"
+#include <stdexcept>
+
using std::deque;
+using std::runtime_error;
+
namespace loader {
return chunk;
}
+unsigned int PagedAllocator::PageOf(void *ptrIn) const {
+ char *ptr = reinterpret_cast<char *>(ptrIn);
+ unsigned int counter = 0;
+ for (deque<char *>::const_iterator i(pages.begin()), end(pages.end()); i != end; ++i, ++counter) {
+ if (ptr < *i) continue;
+ if (*i < ptr) return counter;
+ }
+ throw runtime_error("PagedAllocator::PageOf");
+}
+
+unsigned int PagedAllocator::PageOffsetOf(void *ptrIn) const {
+ char *ptr = reinterpret_cast<char *>(ptrIn);
+ for (deque<char *>::const_iterator i(pages.begin()), end(pages.end()); i != end; ++i) {
+ if (ptr < *i) continue;
+ if (*i < ptr) return ptr - *i;
+ }
+ throw runtime_error("PagedAllocator::PageOffsetOf");
+}
+
unsigned int PagedAllocator::Free() const {
return pageSize - (head - CurrentPage());
}
public:
char *Alloc(unsigned int size);
+ unsigned int PageOf(void *) const;
+ unsigned int PageOffsetOf(void *) const;
+
private:
unsigned int Free() const;
void NewPage();
} else {
fields.insert(std::make_pair(n, f));
}
+ if (f.IsReferenced() || f.IsAggregate()) {
+ link = true;
+ }
}
bool TypeDescription::HasField(const std::string &name) const {
}
+int TypeDescription::GetMaxSize() {
+ int max = 0;
+ for (map<int, TypeDescription>::const_iterator
+ i(typeDescriptions.begin()),
+ end(typeDescriptions.end());
+ i != end; ++i) {
+ if (i->second.Size() > max) {
+ max = i->second.Size();
+ }
+ }
+ return max;
+}
+
+
void TypeDescription::WriteSourceWiki(std::ostream &out) {
vector<string> types;
for (map<int, TypeDescription>::const_iterator i(typeDescriptions.begin()), end(typeDescriptions.end()); i != end; ++i) {
const FieldDescription &GetField(const std::string &name) const;
void Construct(void *) const;
void Load(void *) const;
+ bool NeedsLinking() const { return link; }
void SetConstructor(void (*ctor)(void *)) { constructor = ctor; }
void SetLoader(void (*ld)(void *)) { loader = ld; }
static int GetTypeId(const std::string &);
static const TypeDescription &Get(int id);
+ static int GetMaxSize();
+
static void WriteSourceWiki(std::ostream &);
private:
- TypeDescription(int id, const std::string &name) : constructor(0), loader(0), description(0), name(name), id(id), size(0) { }
+ TypeDescription(int id, const std::string &name) : constructor(0), loader(0), description(0), name(name), id(id), size(0), link(false) { }
private:
void (*constructor)(void *);
std::map<int, std::ptrdiff_t> supertypes;
int id;
int size;
+ bool link;
static std::map<int, TypeDescription> typeDescriptions;
static std::map<std::string, int> typeName2ID;
#include "common/Script.h"
#include "common/Spell.h"
#include "common/Stats.h"
-#include "math/Fixed.h"
-#include "math/Vector.h"
#include "graphics/CharSelect.h"
#include "graphics/ComplexAnimation.h"
#include "graphics/Font.h"
#include "graphics/Sprite.h"
#include "graphics/Texture.h"
#include "loader/Caster.h"
+#include "loader/Compiler.h"
#include "loader/Interpreter.h"
#include "loader/Loader.h"
#include "loader/ParsedSource.h"
#include "map/MapState.h"
#include "map/Tile.h"
#include "map/Trigger.h"
+#include "math/Fixed.h"
+#include "math/Vector.h"
#include "menu/Resources.h"
#include "sdl/InitImage.h"
#include "sdl/InitScreen.h"
using common::GameState;
using common::Hero;
using common::Spell;
-using math::Fixed;
-using math::Vector;
using graphics::Texture;
using loader::Caster;
+using loader::Compiler;
using loader::Interpreter;
using loader::Loader;
using loader::ParsedSource;
using loader::TypeDescription;
using map::Entity;
using map::MapState;
+using math::Fixed;
+using math::Vector;
using sdl::InitImage;
using sdl::InitScreen;
using sdl::InitSDL;
}
}
+ Interpreter intp(source);
+ intp.ReadSource();
+
switch (args.GetRunLevel()) {
case Arguments::WRITE:
{
break;
}
case 'o': {
- std::ofstream outstream(args.OutfilePath());
+ std::fstream outstream(args.OutfilePath(), std::ios_base::out|std::ios_base::trunc);
+ outstream.flush();
+ outstream.close();
+ outstream.open(args.OutfilePath());
+ outstream.exceptions(std::ios_base::badbit|std::ios_base::failbit);
Compiler(intp).Write(outstream);
break;
+ }
default: {
throw std::runtime_error(string("don't know how to write file ") + args.OutfilePath());
}
break;
}
- Interpreter intp(source);
- intp.ReadSource();
-
if (intp.PostponedDefinitions().size() > 0) {
for (vector<Interpreter::PostponedDefinition>::const_iterator i(intp.PostponedDefinitions().begin()), end(intp.PostponedDefinitions().end()); i != end; ++i) {
std::cerr << "missing definition of " << TypeDescription::Get(i->type).TypeName() << " " << i->identifier << std::endl;