summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 1a28b45)
raw | patch | inline | side by side (parent: 1a28b45)
author | Gert van Valkenhoef <g.h.m.van.valkenhoef@rug.nl> | |
Tue, 15 Nov 2011 17:52:36 +0000 (17:52 +0000) | ||
committer | Gert van Valkenhoef <g.h.m.van.valkenhoef@rug.nl> | |
Tue, 15 Nov 2011 17:52:36 +0000 (17:52 +0000) |
21 files changed:
diff --git a/Makefile b/Makefile
index 90f9d3d94966421d0f16474a58357adfad2c0f6c..260da917104710eaf8c5c5f7a0f6dca5c2015ed2 100644 (file)
--- a/Makefile
+++ b/Makefile
-MODULES := reader store alien typeregister textmodel fold
+MODULES := reader store alien typeregister textmodel fold typepath
# Add module directories to the include path
CFLAGS += -I.
diff --git a/reader/Make.inc b/reader/Make.inc
index caf7946303da7643121f0e69df9888f5bfd72dde..6f5e81a97d9327feabe88724a99cf777d276c321 100644 (file)
--- a/reader/Make.inc
+++ b/reader/Make.inc
-SRCS += reader/reader.cc reader/util.cc
+READER_SRC := addPathComponent.cc fixTypeName.cc readAlien.cc reader.cc \
+ readLinkStore.cc readNewLinkStore.cc readNilStore.cc readPath.cc \
+ readStore.cc readStoreOrElemStore.cc readVersion.cc util.cc
+SRCS += $(patsubst %,reader/%,$(READER_SRC))
diff --git a/reader/addPathComponent.cc b/reader/addPathComponent.cc
--- /dev/null
@@ -0,0 +1,14 @@
+#include "reader/reader.ih"
+
+namespace odc {
+
+void Reader::addPathComponent(bool first, const std::string &typeName) {
+ int next = d_typeList.size();
+ int curr = next - 1;
+ if (!first) {
+ d_typeList[curr]->baseId = next;
+ }
+ d_typeList.push_back(new TypeEntry(typeName));
+}
+
+} // namespace odc
diff --git a/reader/fixTypeName.cc b/reader/fixTypeName.cc
--- /dev/null
+++ b/reader/fixTypeName.cc
@@ -0,0 +1,13 @@
+#include "reader/reader.ih"
+
+namespace odc {
+
+std::string &Reader::fixTypeName(std::string &name) {
+ size_t pos = name.size() - 4;
+ if (pos > 0 && name.substr(pos, 4).compare("Desc") == 0) {
+ return name.replace(pos, 4, "^");
+ }
+ return name;
+}
+
+} // namespace odc
diff --git a/reader/readAlien.cc b/reader/readAlien.cc
--- /dev/null
+++ b/reader/readAlien.cc
@@ -0,0 +1,23 @@
+#include "reader/reader.ih"
+
+namespace odc {
+
+void Reader::readAlien(Alien *alien, std::streampos down, std::streampos end) {
+ std::streampos next = down != 0 ? down : end;
+ while (d_rider.tellg() < end) {
+ if (d_rider.tellg() < next) { // for some reason, this means its a piece (unstructured)
+ size_t len = next - d_rider.tellg();
+ char *buf = new char[len];
+ d_rider.read(buf, len);
+ AlienComponent *comp = new AlienPiece(buf, len);
+ alien->getComponents().push_back(comp);
+ } else { // that means we've got a store
+ d_rider.seekg(next);
+ AlienComponent *comp = new AlienPart(readStore());
+ alien->getComponents().push_back(comp);
+ next = d_state->next > 0 ? d_state->next : end;
+ }
+ }
+}
+
+} // namespace odc
diff --git a/reader/readLinkStore.cc b/reader/readLinkStore.cc
--- /dev/null
+++ b/reader/readLinkStore.cc
@@ -0,0 +1,15 @@
+
+#include "reader/reader.ih"
+
+namespace odc {
+
+Store *Reader::readLinkStore() {
+ throw "Reader::readLinkStore() not implemented";
+}
+// ELSIF kind = link THEN
+// rd.ReadInt(id); rd.ReadInt(comment); rd.ReadInt(next);
+// rd.st.end := rd.Pos();
+// IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
+// x := ThisStore(rd.eDict, id)
+
+} // namespace odc
diff --git a/reader/readNewLinkStore.cc b/reader/readNewLinkStore.cc
--- /dev/null
@@ -0,0 +1,14 @@
+#include "reader/reader.ih"
+
+namespace odc {
+
+Store *Reader::readNewLinkStore() {
+ throw "Reader::readNewLinkStore() not implemented";
+}
+// ELSIF kind = newlink THEN
+// rd.ReadInt(id); rd.ReadInt(comment); rd.ReadInt(next);
+// rd.st.end := rd.Pos();
+// IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
+// x := ThisStore(rd.sDict, id)
+
+} // namespace odc
diff --git a/reader/readNilStore.cc b/reader/readNilStore.cc
--- /dev/null
+++ b/reader/readNilStore.cc
@@ -0,0 +1,22 @@
+#include "reader/reader.ih"
+
+namespace odc {
+
+Store *Reader::readNilStore() {
+ INTEGER comment = readInt();
+ std::streamoff next = readInt();
+ d_state->end = d_rider.tellg();
+ if (next > 0 || (next == 0 && comment % 2 == 1)) {
+ d_state->next = d_state->end + next;
+ } else {
+ d_state->next = 0;
+ }
+ return 0;
+}
+// IF kind = nil THEN
+// rd.ReadInt(comment); rd.ReadInt(next);
+// rd.st.end := rd.Pos();
+// IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
+// x := NIL
+
+} // namespace odc
diff --git a/reader/readPath.cc b/reader/readPath.cc
--- /dev/null
+++ b/reader/readPath.cc
@@ -0,0 +1,42 @@
+#include "reader/reader.ih"
+
+namespace odc {
+
+TypePath Reader::readPath() {
+ TypePath path;
+ SHORTCHAR kind = readSChar();
+ SHORTCHAR *buf = new SHORTCHAR[64]; // TypeName has a maximum of length 64 (including terminator).
+ int i;
+ for (i = 0; kind == Store::NEWEXT; ++i) {
+ readSString(buf);
+ std::string name(buf);
+ path.push_back(fixTypeName(name));
+ addPathComponent(i == 0, path[i]);
+// IF path[i] # elemTName THEN INC(i) END;
+ kind = readSChar();
+ }
+
+ if (kind == Store::NEWBASE) {
+ readSString(buf);
+ std::string name(buf);
+ path.push_back(fixTypeName(name));
+ addPathComponent(i == 0, path[i]);
+ ++i;
+ } else if (kind == Store::OLDTYPE) {
+ int id = readInt();
+ if (i > 0) {
+ d_typeList[d_typeList.size() - 1]->baseId = id;
+ }
+ while (id != -1) {
+ path.push_back(d_typeList[id]->name);
+ id = d_typeList[id]->baseId;
+// IF path[i] # elemTName THEN INC(i) END
+ ++i;
+ }
+ } else {
+ throw 100;
+ }
+ return path;
+}
+
+} // namespace odc
diff --git a/reader/readStore.cc b/reader/readStore.cc
--- /dev/null
+++ b/reader/readStore.cc
@@ -0,0 +1,28 @@
+#include "reader/reader.ih"
+
+namespace odc {
+
+Store* Reader::readStore() {
+ SHORTCHAR kind = readSChar();
+ if (kind == Store::NIL) {
+ //std::cout << "NIL STORE" << std::endl;
+ return readNilStore();
+ } else if (kind == Store::LINK) {
+ //std::cout << "LINK STORE" << std::endl;
+ return readLinkStore();
+ } else if (kind == Store::NEWLINK) {
+ //std::cout << "NEWLINK STORE" << std::endl;
+ return readNewLinkStore();
+ } else if (kind == Store::STORE) {
+ //std::cout << "STORE STORE" << std::endl;
+ return readStoreOrElemStore(false);
+ } else if (kind == Store::ELEM) {
+ //std::cout << "ELEM STORE" << std::endl;
+ return readStoreOrElemStore(true);
+ } else {
+ //std::cout << std::hex << (unsigned int)kind << std::endl;
+ throw 20;
+ }
+}
+
+} // namespace odc
diff --git a/reader/readStoreOrElemStore.cc b/reader/readStoreOrElemStore.cc
--- /dev/null
@@ -0,0 +1,108 @@
+#include "reader/reader.ih"
+
+namespace odc {
+
+Store *Reader::readStoreOrElemStore(bool isElem) {
+ INTEGER id = isElem ? d_elemList.size() : d_storeList.size();
+ TypePath path = readPath();
+ //std::cout << path.toString() << std::endl;
+ const std::string &type = path[0];
+ INTEGER comment = readInt();
+ std::streampos pos1 = d_rider.tellg();
+ std::streamoff next = readInt();
+ std::streamoff down = readInt();
+ std::streamoff len = readInt();
+ std::streampos pos = d_rider.tellg();
+ if (next > 0) {
+ d_state->next = pos1 + next + (std::streamoff)4;
+ } else {
+ d_state->next = 0;
+ }
+ int downPos = 0;
+ if (down > 0) {
+ downPos = pos1 + down + (std::streamoff)8;
+ }
+ d_state->end = pos + len;
+ d_cause = 0;
+ assert(len >= 0);
+ if (next != 0) {
+ assert(d_state->next > pos1);
+ if (down != 0) {
+ assert(downPos < d_state->next);
+ }
+ }
+ if (down > 0) {
+ assert(downPos > pos1);
+ assert(downPos < d_state->end);
+ }
+
+ const TypeProxyBase *t = TypeRegister::getInstance().get(type); // FIXME type lookup here
+ Store *x = 0;
+ if (t != 0) {
+ x = t->newInstance(id);
+ } else {
+ d_cause = TYPENOTFOUND;
+ }
+
+ if (x != 0) { // IF READING SUCCEEDS, INSERT MORE CHECKS HERE
+ if (true) { // samePath(x, path)
+ ReaderState *save = d_state;
+ d_state = new ReaderState();
+ x->internalize(*this);
+ delete d_state;
+ d_state = save;
+
+ if (d_cause != 0) {
+ x = 0;
+ }
+ assert(d_rider.tellg() == d_state->end);
+ assert(!d_rider.eof());
+ } else {
+// rd.cause := inconsistentType; AlienTypeReport(rd.cause, type);
+ x = 0;
+ }
+ }
+
+ if (x != 0) {
+ if (d_store == 0) {
+ d_store = x;
+ } else {
+ // join(d_store, x)
+ }
+ if (isElem) {
+ d_elemList.push_back(x);
+ } else {
+ d_storeList.push_back(x);
+ }
+ } else {
+ d_rider.seekg(pos); // x->internalize() could have left us anywhere
+ assert(d_cause != 0);
+ Alien *alien = new Alien(id, path); //, d_cause); //,file
+ if (d_store == 0) {
+ d_store = alien;
+ } else {
+ // join(d_store, alien)
+ }
+ if (isElem) {
+ d_elemList.push_back(alien);
+ } else {
+ d_storeList.push_back(alien);
+ }
+ ReaderState *save = d_state;
+ d_state = new ReaderState();
+ readAlien(alien, downPos, save->end);
+ delete d_state;
+ d_state = save;
+ assert(d_rider.tellg() == d_state->end);
+
+ // we've just read the alien, so reset the state
+ d_cause = 0;
+ d_cancelled = false;
+ d_readAlien = true;
+ return alien;
+ }
+
+ return x;
+}
+
+} // namespace odc
diff --git a/reader/readVersion.cc b/reader/readVersion.cc
--- /dev/null
+++ b/reader/readVersion.cc
@@ -0,0 +1,13 @@
+#include "reader/reader.ih"
+
+namespace odc {
+
+INTEGER Reader::readVersion(INTEGER min, INTEGER max) {
+ INTEGER version = readByte();
+ if (version < min || version > max) {
+ turnIntoAlien(ALIENVERSION);
+ }
+ return version;
+}
+
+} // namespace odc
diff --git a/reader/reader.cc b/reader/reader.cc
index 9f3402ce370f8ee5afba72bbf618bbe7784be963..1395bba09f9592d5dcf77ca9770838d01d81d536 100644 (file)
--- a/reader/reader.cc
+++ b/reader/reader.cc
-#include "reader/reader.h"
-#include "alien/alien.h"
-
-#include <string>
-#include <assert.h>
+#include "reader/reader.ih"
namespace odc {
return d_cancelled;
}
-INTEGER Reader::readVersion(INTEGER min, INTEGER max) {
- INTEGER version = readByte();
- if (version < min || version > max) {
- turnIntoAlien(ALIENVERSION);
- }
- return version;
-}
-
-Store* Reader::readStore() {
- SHORTCHAR kind = readSChar();
- if (kind == Store::NIL) {
- //std::cout << "NIL STORE" << std::endl;
- return readNilStore();
- } else if (kind == Store::LINK) {
- //std::cout << "LINK STORE" << std::endl;
- return readLinkStore();
- } else if (kind == Store::NEWLINK) {
- //std::cout << "NEWLINK STORE" << std::endl;
- return readNewLinkStore();
- } else if (kind == Store::STORE) {
- //std::cout << "STORE STORE" << std::endl;
- return readStoreOrElemStore(false);
- } else if (kind == Store::ELEM) {
- //std::cout << "ELEM STORE" << std::endl;
- return readStoreOrElemStore(true);
- } else {
- //std::cout << std::hex << (unsigned int)kind << std::endl;
- throw 20;
- }
-}
-// PROCEDURE (VAR rd: Reader) ReadStore* (OUT x: Store), NEW;
-// VAR a: Alien; t: Kernel.Type;
-// len, pos, pos1, id, comment, next, down, downPos, nextTypeId, nextElemId, nextStoreId: INTEGER;
-// kind: SHORTCHAR; path: TypePath; type: TypeName;
-// save: ReaderState;
-
-Store *Reader::readNilStore() {
- INTEGER comment = readInt();
- std::streamoff next = readInt();
- d_state->end = d_rider.tellg();
- if (next > 0 || (next == 0 && comment % 2 == 1)) {
- d_state->next = d_state->end + next;
- } else {
- d_state->next = 0;
- }
- return 0;
-}
-// IF kind = nil THEN
-// rd.ReadInt(comment); rd.ReadInt(next);
-// rd.st.end := rd.Pos();
-// IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
-// x := NIL
-
-Store *Reader::readLinkStore() {
- throw "Reader::readLinkStore() not implemented";
-}
-// ELSIF kind = link THEN
-// rd.ReadInt(id); rd.ReadInt(comment); rd.ReadInt(next);
-// rd.st.end := rd.Pos();
-// IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
-// x := ThisStore(rd.eDict, id)
-
-Store *Reader::readNewLinkStore() {
- throw "Reader::readNewLinkStore() not implemented";
-}
-// ELSIF kind = newlink THEN
-// rd.ReadInt(id); rd.ReadInt(comment); rd.ReadInt(next);
-// rd.st.end := rd.Pos();
-// IF (next > 0) OR ((next = 0) & ODD(comment)) THEN rd.st.next := rd.st.end + next ELSE rd.st.next := 0 END;
-// x := ThisStore(rd.sDict, id)
-
-Store *Reader::readStoreOrElemStore(bool isElem) {
- INTEGER id = isElem ? d_elemList.size() : d_storeList.size();
- TypePath path = readPath();
- //std::cout << path.toString() << std::endl;
- const std::string &type = path[0];
- INTEGER comment = readInt();
- std::streampos pos1 = d_rider.tellg();
- std::streamoff next = readInt();
- std::streamoff down = readInt();
- std::streamoff len = readInt();
- std::streampos pos = d_rider.tellg();
- if (next > 0) {
- d_state->next = pos1 + next + (std::streamoff)4;
- } else {
- d_state->next = 0;
- }
- int downPos = 0;
- if (down > 0) {
- downPos = pos1 + down + (std::streamoff)8;
- }
- d_state->end = pos + len;
- d_cause = 0;
- assert(len >= 0);
- if (next != 0) {
- assert(d_state->next > pos1);
- if (down != 0) {
- assert(downPos < d_state->next);
- }
- }
- if (down > 0) {
- assert(downPos > pos1);
- assert(downPos < d_state->end);
- }
-
- const TypeProxyBase *t = TypeRegister::getInstance().get(type); // FIXME type lookup here
- Store *x = 0;
- if (t != 0) {
- x = t->newInstance(id);
- } else {
- d_cause = TYPENOTFOUND;
- }
-
- if (x != 0) { // IF READING SUCCEEDS, INSERT MORE CHECKS HERE
- if (true) { // samePath(x, path)
- ReaderState *save = d_state;
- d_state = new ReaderState();
- x->internalize(*this);
- delete d_state;
- d_state = save;
-
- if (d_cause != 0) {
- x = 0;
- }
- assert(d_rider.tellg() == d_state->end);
- assert(!d_rider.eof());
- } else {
-// rd.cause := inconsistentType; AlienTypeReport(rd.cause, type);
- x = 0;
- }
- }
-
- if (x != 0) {
- if (d_store == 0) {
- d_store = x;
- } else {
- // join(d_store, x)
- }
- if (isElem) {
- d_elemList.push_back(x);
- } else {
- d_storeList.push_back(x);
- }
- } else {
- d_rider.seekg(pos); // x->internalize() could have left us anywhere
- assert(d_cause != 0);
- Alien *alien = new Alien(id, path); //, d_cause); //,file
- if (d_store == 0) {
- d_store = alien;
- } else {
- // join(d_store, alien)
- }
- if (isElem) {
- d_elemList.push_back(alien);
- } else {
- d_storeList.push_back(alien);
- }
- ReaderState *save = d_state;
- d_state = new ReaderState();
- internalizeAlien(alien, downPos, save->end);
- delete d_state;
- d_state = save;
- assert(d_rider.tellg() == d_state->end);
-
- // we've just read the alien, so reset the state
- d_cause = 0;
- d_cancelled = false;
- d_readAlien = true;
- return alien;
- }
-
- return x;
-}
-
-
-void Reader::internalizeAlien(Alien *alien, std::streampos down, std::streampos end) {
- std::streampos next = down != 0 ? down : end;
- while (d_rider.tellg() < end) {
- if (d_rider.tellg() < next) { // for some reason, this means its a piece (unstructured)
- size_t len = next - d_rider.tellg();
- char *buf = new char[len];
- d_rider.read(buf, len);
- AlienComponent *comp = new AlienPiece(buf, len);
- alien->getComponents().push_back(comp);
- } else { // that means we've got a store
- d_rider.seekg(next);
- AlienComponent *comp = new AlienPart(readStore());
- alien->getComponents().push_back(comp);
- next = d_state->next > 0 ? d_state->next : end;
- }
- }
-}
-
-std::string &Reader::fixTypeName(std::string &name) {
- size_t pos = name.size() - 4;
- if (pos > 0 && name.substr(pos, 4).compare("Desc") == 0) {
- return name.replace(pos, 4, "^");
- }
- return name;
-}
-
-TypePath Reader::readPath() {
- TypePath path;
- SHORTCHAR kind = readSChar();
- SHORTCHAR *buf = new SHORTCHAR[64]; // TypeName has a maximum of length 64 (including terminator).
- int i;
- for (i = 0; kind == Store::NEWEXT; ++i) {
- readSString(buf);
- std::string name(buf);
- path.push_back(fixTypeName(name));
- addPathComponent(i == 0, path[i]);
-// IF path[i] # elemTName THEN INC(i) END;
- kind = readSChar();
- }
-
- if (kind == Store::NEWBASE) {
- readSString(buf);
- std::string name(buf);
- path.push_back(fixTypeName(name));
- addPathComponent(i == 0, path[i]);
- ++i;
- } else if (kind == Store::OLDTYPE) {
- int id = readInt();
- if (i > 0) {
- d_typeList[d_typeList.size() - 1]->baseId = id;
- }
- while (id != -1) {
- path.push_back(d_typeList[id]->name);
- id = d_typeList[id]->baseId;
-// IF path[i] # elemTName THEN INC(i) END
- ++i;
- }
- } else {
- throw 100;
- }
- return path;
-}
-
-void Reader::addPathComponent(bool first, const std::string &typeName) {
- int next = d_typeList.size();
- int curr = next - 1;
- if (!first) {
- d_typeList[curr]->baseId = next;
- }
- d_typeList.push_back(new TypeEntry(typeName));
-}
-
} // namespace odc
diff --git a/reader/reader.h b/reader/reader.h
index eb593b5859c074ea74410895d5da467668720164..7c843c18deada672ef97ad966f918da1244ca9b3 100644 (file)
--- a/reader/reader.h
+++ b/reader/reader.h
#include <vector>
#include "oberon.h"
-#include "store/store.h"
-#include "alien/alien.h"
+#include "typepath/typepath.h"
namespace odc {
+class Store;
+class Alien;
+
struct TypeEntry {
const std::string name;
INTEGER baseId;
/**
* Read an alien store.
*/
- void internalizeAlien(Alien *alien, std::streampos down, std::streampos end);
+ void readAlien(Alien *alien, std::streampos down, std::streampos end);
/**
* Make store name consistent with names found in BlackBox source.
diff --git a/reader/reader.ih b/reader/reader.ih
--- /dev/null
+++ b/reader/reader.ih
@@ -0,0 +1,7 @@
+#include "reader/reader.h"
+
+#include "store/store.h"
+#include "alien/alien.h"
+
+#include <string>
+#include <assert.h>
diff --git a/store/store.cc b/store/store.cc
index c85d831b7e058f2d525860c9105e3e61aca415e5..76f0586f3fcf6d714114366bfdd4c80bec024d4f 100644 (file)
--- a/store/store.cc
+++ b/store/store.cc
#include <iostream>
-
namespace odc {
-template<class T, class A> T join(const A & begin, const A & end, const T &sep) {
- T result;
-
- if (begin != end) {
- A it = begin;
- result.append(*it);
- for (++it; it != end; ++it) {
- result.append(sep).append(*it);
- }
- }
-
- return result;
-}
-
-std::string TypePath::toString() const {
- return join(begin(), end(), std::string("->"));
-}
-
const std::string Store::TYPENAME("Stores.Store^");
const TopTypeProxy<Store> Store::PROXY;
diff --git a/store/store.h b/store/store.h
index 5743cb09f938ff770840fa32ed610e70d16eb9fe..b21f9f86eaa207284dcb544d844d9822915f764f 100644 (file)
--- a/store/store.h
+++ b/store/store.h
#include "oberon.h"
#include "typeregister/typeregister.h"
#include "visitor/visitor.h"
+#include "typepath/typepath.h"
namespace odc {
class Reader; // forward decl
- class TypePath : public std::vector<std::string> {
- public:
- std::string toString() const;
- };
-
/**
* TYPE Store
* ABSTRACT
diff --git a/typepath/Make.inc b/typepath/Make.inc
--- /dev/null
+++ b/typepath/Make.inc
@@ -0,0 +1 @@
+SRCS += typepath/toString.cc
diff --git a/typepath/toString.cc b/typepath/toString.cc
--- /dev/null
+++ b/typepath/toString.cc
@@ -0,0 +1,23 @@
+#include "typepath/typepath.ih"
+
+namespace odc {
+
+template<class T, class A> T join(const A & begin, const A & end, const T &sep) {
+ T result;
+
+ if (begin != end) {
+ A it = begin;
+ result.append(*it);
+ for (++it; it != end; ++it) {
+ result.append(sep).append(*it);
+ }
+ }
+
+ return result;
+}
+
+std::string TypePath::toString() const {
+ return join(begin(), end(), std::string("->"));
+}
+
+} // namespace odc
diff --git a/typepath/typepath.h b/typepath/typepath.h
--- /dev/null
+++ b/typepath/typepath.h
@@ -0,0 +1,16 @@
+#ifndef _TYPEPATH_H_
+#define _TYPEPATH_H_
+
+#include <vector>
+#include <string>
+
+namespace odc {
+
+ class TypePath : public std::vector<std::string> {
+ public:
+ std::string toString() const;
+ };
+
+}
+
+#endif // _TYPEPATH_H_
diff --git a/typepath/typepath.ih b/typepath/typepath.ih
--- /dev/null
+++ b/typepath/typepath.ih
@@ -0,0 +1 @@
+#include "typepath/typepath.h"