DEADSOFTWARE

Add some error handling, close to understanding StdTextModel
authorGert van Valkenhoef <g.h.m.van.valkenhoef@rug.nl>
Wed, 10 Aug 2011 20:12:41 +0000 (21:12 +0100)
committerGert van Valkenhoef <g.h.m.van.valkenhoef@rug.nl>
Wed, 10 Aug 2011 20:12:41 +0000 (21:12 +0100)
Makefile
odcread.cc
reader.cc
reader.h
store.cc
store.h
textmodel.cc [new file with mode: 0644]
textmodel.h [new file with mode: 0644]

index 1ad67d51ef4708a3a483dab9a454343be7b3618f..c933edc1a60e9aae1f39808e273438968abc6abc 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 HEADERS=oberon.h store.h reader.h domain.h alien.h typeregister.h
 
-odcread: odcread.o reader.o store.o util.o alien.o typeregister.o
+odcread: odcread.o reader.o store.o util.o alien.o typeregister.o textmodel.o
        g++ -o $@ $^
 
 %.o: %.cc $(HEADERS)
index e049bb071e7bd90a263bbca7043cb66c930123a2..c843713451fae3916191777dd283528713841fa7 100644 (file)
@@ -33,6 +33,8 @@ int main(int argc, char *argv[]) {
        std::cout << s->toString() << std::endl;
        std::cout << in.tellg() << " " << in.eof() << std::endl;
 
-       std::cout << odc::ContainerModel(0).getTypePath().toString() << std::endl;
+       odc::TypePath path;
+       odc::ContainerModel(0).getTypePath(&path);
+       std::cout << path.toString() << std::endl;
        return 0;
 }
index 3ccfb7144bae80159e5172977dd3e9f475a55de9..b027bd57299f3347c75b7c87d98c8dbcddc73c37 100644 (file)
--- a/reader.cc
+++ b/reader.cc
@@ -2,6 +2,7 @@
 #include <alien.h>
 
 #include <string>
+#include <assert.h>
 
 namespace odc {
 
@@ -38,11 +39,22 @@ void Reader::readSString(SHORTCHAR *out) {
        }
 }
 
+void Reader::turnIntoAlien(int cause) {
+       assert(cause > 0);
+       d_cancelled = true;
+       d_cause = cause;
+       d_readAlien = true;
+}
+
+bool Reader::isCancelled() {
+       return d_cancelled;
+}
+
 INTEGER Reader::readVersion(INTEGER min, INTEGER max) {
        INTEGER version = readByte();
-       //if (version < min || version > max) {
-               //                      rd.TurnIntoAlien(alienVersion)
-       //}
+       if (version < min || version > max) {
+               turnIntoAlien(ALIENVERSION);
+       }
        return version;
 }
 
@@ -64,6 +76,7 @@ Store* Reader::readStore() {
                std::cout << "ELEM STORE" << std::endl;
                return readStoreOrElemStore(true);
        } else {
+               std::cout << std::hex << (unsigned int)kind << std::endl;
                throw 20;
        }
 }
@@ -119,34 +132,60 @@ Store *Reader::readStoreOrElemStore(bool isElem) {
        }
        d_state->end = pos + len;
        d_cause = 0;
-       // FIXME: insert whole bunch of checks here
-//                     ASSERT(len >= 0, 101);
-//                     IF next # 0 THEN
-//                             ASSERT(rd.st.next > pos1, 102);
-//                             IF down # 0 THEN
-//                                     ASSERT(downPos < rd.st.next, 103)
-//                             END
-//                     END;
-//                     IF down # 0 THEN
-//                             ASSERT(downPos > pos1, 104);
-//                             ASSERT(downPos < rd.st.end, 105)
-//                     END;
+       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);
-               x->internalize(*this);
-//                             x := NewStore(t); x.isElem := kind = elem
        } else {
-//                             rd.cause := thisTypeRes; AlienTypeReport(rd.cause, type);
-//                             x := NIL
+               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)
+                       std::cout << "Man, should have written join(.,.)" << std::endl;
+               }
+               if (isElem) {
+                       d_elemList.push_back(x);
+               } else {
+                       d_storeList.push_back(x);
+               }
        } else {
-//                             rd.SetPos(pos);
-//                             ASSERT(rd.cause # 0, 107);
+               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;
@@ -160,74 +199,21 @@ Store *Reader::readStoreOrElemStore(bool isElem) {
                        d_storeList.push_back(alien);
                }
                ReaderState *save = d_state;
-//                             rd.nextTypeId := nextTypeId; rd.nextElemId := nextElemId; rd.nextStoreId := nextStoreId;
+               d_state = new ReaderState();
                internalizeAlien(alien, downPos, save->end);
+               delete d_state;
                d_state = save;
-//                             ASSERT(rd.Pos() = rd.st.end, 108);
-//                             rd.cause := 0; rd.cancelled :=  FALSE; rd.readAlien := TRUE
+               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;
 }
-//                     t := ThisType(type);
-//                     IF t # NIL THEN
-//                             x := NewStore(t); x.isElem := kind = elem
-//                     ELSE
-//                             rd.cause := thisTypeRes; AlienTypeReport(rd.cause, type);
-//                             x := NIL
-//                     END;
-//                     IF x # NIL THEN
-//                             IF SamePath(t, path) THEN
-//                                     IF kind = elem THEN
-//                                             x.id := id; AddStore(rd.eDict, rd.eHead, x)
-//                                     ELSE
-//                                             x.id := id; AddStore(rd.sDict, rd.sHead, x)
-//                                     END;
-//                                     save := rd.st; rd.cause := 0; rd.cancelled :=  FALSE;
-//                                     x.Internalize(rd);
-//                                     rd.st := save;
-//                                     IF rd.cause # 0 THEN x := NIL
-//                                     ELSIF (rd.Pos() # rd.st.end) OR rd.rider.eof THEN
-//                                             rd.cause := inconsistentVersion; AlienReport(rd.cause);
-//                                             x := NIL
-//                                     END
-//                             ELSE
-//                                     rd.cause := inconsistentType; AlienTypeReport(rd.cause, type);
-//                                     x := NIL
-//                             END
-//                     END;
-//                     
-//                     IF x # NIL THEN
-//                             IF rd.noDomain THEN
-//                                     rd.store := x;
-//                                     rd.noDomain := FALSE
-//                             ELSE
-//                                     Join(rd.store, x)
-//                             END
-//                     ELSE    (* x is an alien *)
-//                             rd.SetPos(pos);
-//                             ASSERT(rd.cause # 0, 107);
-//                             NEW(a); a.path := path; a.cause := rd.cause; a.file := rd.rider.Base();
-//                             IF rd.noDomain THEN
-//                                     rd.store := a;
-//                                     rd.noDomain := FALSE
-//                             ELSE
-//                                     Join(rd.store, a)
-//                             END;
-//                             IF kind = elem THEN
-//                                     a.id := id; AddStore(rd.eDict, rd.eHead, a)
-//                             ELSE
-//                                     a.id := id; AddStore(rd.sDict, rd.sHead, a)
-//                             END;
-//                             save := rd.st;
-//                             rd.nextTypeId := nextTypeId; rd.nextElemId := nextElemId; rd.nextStoreId := nextStoreId;
-//                             InternalizeAlien(rd, a.comps, downPos, pos, len);
-//                             rd.st := save;
-//                             x := a;
-//                             ASSERT(rd.Pos() = rd.st.end, 108);
-//                             rd.cause := 0; rd.cancelled :=  FALSE; rd.readAlien := TRUE
-//                     END
 
 
 void Reader::internalizeAlien(Alien *alien, std::streampos down, std::streampos end) {
index e9b0234b4972c403099584334386b9d7cb137b62..b4f475ca725bceff119d4f2bd790171995d4bd56 100644 (file)
--- a/reader.h
+++ b/reader.h
@@ -25,6 +25,9 @@ struct TypeEntry {
  */ 
 class Reader {
 private:
+       static const unsigned int TYPENOTFOUND = 1;
+       static const unsigned int ALIENVERSION = 2;
+
        /*
         * rider-: Files.Reader
         * The file rider which links a Reader to a file.
@@ -33,7 +36,7 @@ private:
 
        /*
         * cancelled-: BOOLEAN  valid during a Store.Internalize call
-        * Tells whether the currently executing Internalize has been called by ReadVersion or TurnIntoAlien.
+        * Tells whether the currently executing Internalize has been cancelled by ReadVersion or TurnIntoAlien.
         */
        bool d_cancelled;
 
@@ -43,6 +46,11 @@ private:
         */
        bool d_readAlien;
 
+       /**
+        * Cause of current read being alien.
+        */
+       unsigned int d_cause;
+
        std::vector<TypeEntry*> d_typeList;
 
        std::vector<Store*> d_elemList; // FIXME: WTH, why are these different?
@@ -62,8 +70,6 @@ private:
        };
        ReaderState *d_state;
 
-       INTEGER d_cause;
-
        public:
        /**
         * Construct a reader from the istream rider.
@@ -257,6 +263,9 @@ private:
         * Pre
         * 20   cause > 0
         */
+       void turnIntoAlien(int cause);
+
+       bool isCancelled();
 
        private:
        Store *readStoreOrElemStore(bool isElem);
index ba0842508d6bf15218d54ce4f6c54a84748c529d..c2fd5b4d8696e62da10f8b04b6d4e08488a2a003 100644 (file)
--- a/store.cc
+++ b/store.cc
@@ -26,7 +26,6 @@ std::string TypePath::toString() const {
 
 const std::string Store::TYPENAME("Stores.Store^");
 const TypeProxy<Store> Store::PROXY;
-TypePath *Store::s_typePath = 0;
 
 Store::Store(INTEGER id): d_id(id) {}
 
@@ -46,23 +45,16 @@ const std::string &Store::getTypeName() const {
        return Store::getType();
 }
 
-const TypePath &Store::getTypePath() const {
-       if (s_typePath == 0) {
-               s_typePath = calcTypePath(getTypeName());
-       }
-       return *s_typePath;
+void Store::getTypePath(TypePath *out) const {
+       return calcTypePath(out, getTypeName());
 }
 
-TypePath *Store::calcTypePath(const std::string &name) const {
+void Store::calcTypePath(TypePath *path, const std::string &name) const {
        const std::string *super = TypeRegister::getInstance().get(name)->getSuper();
-       TypePath *path;
        if (super != 0) {
-               path = calcTypePath(*super);
-       } else {
-               path = new TypePath();
+               calcTypePath(path, *super);
        }
        path->push_back(name);
-       return path;
 }
 
 void Store::internalize(Reader &reader) {
@@ -91,7 +83,9 @@ const std::string &Elem::getTypeName() const {
 }
 
 void Elem::internalize(Reader &reader) {
-       Store::internalize(reader); // just being explicit
+       Store::internalize(reader);
+       if (reader.isCancelled()) return;
+       reader.readVersion(0, 0);
 }
 
 const std::string Model::TYPENAME("Models.Model^");
@@ -113,6 +107,7 @@ const std::string &Model::getTypeName() const {
 
 void Model::internalize(Reader &reader) {
        Elem::internalize(reader);
+       if (reader.isCancelled()) return;
        reader.readVersion(0, 0);
 }
 
@@ -135,97 +130,8 @@ const std::string &ContainerModel::getTypeName() const {
 
 void ContainerModel::internalize(Reader &reader) {
        Model::internalize(reader);
+       if (reader.isCancelled()) return;
        reader.readVersion(0, 0);
 }
 
-const std::string TextModel::TYPENAME("TextModels.Model^");
-const TypeProxy<TextModel> TextModel::PROXY;
-
-TextModel::TextModel(INTEGER id) : ContainerModel(id) {}
-
-const std::string &TextModel::getType() {
-       return TYPENAME;
-}
-
-const std::string *TextModel::getSuper() {
-       return &ContainerModel::getType();
-}
-
-const std::string &TextModel::getTypeName() const {
-       return getType();
-}
-
-void TextModel::internalize(Reader &reader) {
-       ContainerModel::internalize(reader);
-       reader.readVersion(0, 0);
-}
-
-const std::string StdTextModel::TYPENAME("TextModels.StdModel^");
-const TypeProxy<StdTextModel> StdTextModel::PROXY;
-
-StdTextModel::StdTextModel(INTEGER id) : TextModel(id) {}
-
-const std::string &StdTextModel::getType() {
-       return TYPENAME;
-}
-
-const std::string *StdTextModel::getSuper() {
-       return &TextModel::getType();
-}
-
-const std::string &StdTextModel::getTypeName() const {
-       return getType();
-}
-
-void StdTextModel::internalize(Reader &reader) {
-       TextModel::internalize(reader);
-       reader.readVersion(0, 1);
-
-//     PROCEDURE (t: StdModel) Internalize (VAR rd: Stores.Reader);
-//             VAR u, un: Run; sp: Piece; lp: LPiece; v: ViewRef;
-//                     org, len: INTEGER; ano: BYTE; thisVersion: INTEGER;
-//                     attr: Attributes; dict: AttrDict;
-//     BEGIN
-//             ASSERT(t.Domain() = NIL, 20); ASSERT(t.len = 0, 21);
-//             t.Internalize^(rd); IF rd.cancelled THEN RETURN END;
-//             rd.ReadVersion(minVersion, maxStdModelVersion, thisVersion);
-//             IF rd.cancelled THEN RETURN END;
-//             StdInit(t);
-//             dict.len := 0; u := t.trailer;
-//             rd.ReadInt(len); org := rd.Pos() + len;
-//             rd.ReadByte(ano);
-//             WHILE ano # -1 DO
-//                     IF ano = dict.len THEN
-//                             ReadAttr(rd, attr); Stores.Join(t, attr);
-//                             IF dict.len < dictSize THEN dict.attr[dict.len] := attr; INC(dict.len) END
-//                     ELSE
-//                             attr := dict.attr[ano]
-//                     END;
-//                     rd.ReadInt(len);
-//                     IF len > 0 THEN (* piece *)
-//                             NEW(sp); sp.len := len; sp.attr := attr;
-//                             sp.file := rd.rider.Base(); sp.org := org; un := sp;
-//                             INC(org, len)
-//                     ELSIF len < 0 THEN      (* longchar piece *)
-//                             len := -len; ASSERT(~ODD(len), 100);
-//                             NEW(lp); lp.len := len DIV 2; lp.attr := attr;
-//                             lp.file := rd.rider.Base(); lp.org := org; un := lp;
-//                             INC(org, len)
-//                     ELSE    (* len = 0  =>  embedded view *)
-//                             NEW(v); v.len := 1; v.attr := attr;
-//                             rd.ReadInt(v.w); rd.ReadInt(v.h); Views.ReadView(rd, v.view);
-//                             v.view.InitContext(NewContext(v, t));
-//                             un := v; INC(org)
-//                     END;
-//                     INC(t.len, un.len); u.next := un; un.prev := u; u := un;
-//                     rd.ReadByte(ano)
-//             END;
-//             rd.SetPos(org);
-//             u.next := t.trailer; t.trailer.prev := u
-//     END Internalize;
-//
-}
-
-
-
 } // namespace odc
diff --git a/store.h b/store.h
index 54438ab4845b72d44b563fa16c1901897b79099a..da8434060bf2af7999e2440fb45e85fb33efaef6 100644 (file)
--- a/store.h
+++ b/store.h
@@ -27,7 +27,6 @@ namespace odc {
        private:
                static const std::string TYPENAME;
                static const TypeProxy<Store> PROXY;
-               static TypePath *s_typePath;
 
                INTEGER d_id;
 
@@ -63,7 +62,7 @@ namespace odc {
                 * Get the TypePath to this object's type.
                 * @see TypePath
                 */
-               const TypePath &getTypePath() const;
+               void getTypePath(TypePath *path) const;
 
                /**
                 * PROCEDURE (s: Store) Domain (): Domain
@@ -133,7 +132,7 @@ namespace odc {
                virtual std::string toString();
 
                private:
-               TypePath *calcTypePath(const std::string &name) const;
+               void calcTypePath(TypePath * out, const std::string &name) const;
        };
 
        class Elem : public Store {
@@ -200,32 +199,6 @@ namespace odc {
                virtual const std::string &getTypeName() const;
                virtual void internalize(Reader &reader);
        };
-
-       class TextModel : public ContainerModel {
-               private:
-               static const std::string TYPENAME;
-               static const TypeProxy<TextModel> PROXY;
-
-               public:
-               TextModel(INTEGER id);
-               static const std::string &getType();
-               static const std::string *getSuper();
-               virtual const std::string &getTypeName() const;
-               virtual void internalize(Reader &reader);
-       };
-
-       class StdTextModel : public TextModel {
-               private:
-               static const std::string TYPENAME;
-               static const TypeProxy<StdTextModel> PROXY;
-
-               public:
-               StdTextModel(INTEGER id);
-               static const std::string &getType();
-               static const std::string *getSuper();
-               virtual const std::string &getTypeName() const;
-               virtual void internalize(Reader &reader);
-       };
 }
 
 #endif // _STORE_H_
diff --git a/textmodel.cc b/textmodel.cc
new file mode 100644 (file)
index 0000000..bc76a32
--- /dev/null
@@ -0,0 +1,138 @@
+#include <textmodel.h>
+#include <reader.h>
+
+#include <vector>
+
+namespace odc {
+
+const std::string TextModel::TYPENAME("TextModels.Model^");
+const TypeProxy<TextModel> TextModel::PROXY;
+
+TextModel::TextModel(INTEGER id) : ContainerModel(id) {}
+
+const std::string &TextModel::getType() {
+       return TYPENAME;
+}
+
+const std::string *TextModel::getSuper() {
+       return &ContainerModel::getType();
+}
+
+const std::string &TextModel::getTypeName() const {
+       return getType();
+}
+
+void TextModel::internalize(Reader &reader) {
+       ContainerModel::internalize(reader);
+       if (reader.isCancelled()) return;
+       reader.readVersion(0, 0);
+}
+
+const std::string StdTextModel::TYPENAME("TextModels.StdModel^");
+const TypeProxy<StdTextModel> StdTextModel::PROXY;
+
+StdTextModel::StdTextModel(INTEGER id) : TextModel(id) {}
+
+const std::string &StdTextModel::getType() {
+       return TYPENAME;
+}
+
+const std::string *StdTextModel::getSuper() {
+       return &TextModel::getType();
+}
+
+const std::string &StdTextModel::getTypeName() const {
+       return getType();
+}
+
+/*
+ * This is my current theory of how the StdTextModel storage format works:
+ * byte 0: version
+ * byte 1-5: len (length of piece descriptions)
+ * byte 6-5+len: piece descriptions
+ * byte 6+len-end: pieces (length of each defined in piece descriptions)
+ */
+void StdTextModel::internalize(Reader &reader) {
+       TextModel::internalize(reader);
+       if (reader.isCancelled()) return;
+       reader.readVersion(0, 1);
+       if (reader.isCancelled()) return;
+
+       std::vector<Store *> dict;
+       INTEGER len = reader.readInt();
+       BYTE ano = reader.readByte();
+       std::cout << "len " << len << " ano " << (int)ano << std::endl;
+       while (ano != -1) {
+               if (ano == dict.size()) {
+                       Store *attr = reader.readStore(); // readAttributes(); Stores.Join(t, attr)
+                       dict.push_back(attr);
+               }
+               INTEGER pieceLen = reader.readInt();
+               if (pieceLen > 0) { // shortchar piece
+                       std::cout << "Found SChar piece" << std::endl;
+//                             NEW(sp); sp.len := len; sp.attr := attr;
+//                             sp.file := rd.rider.Base(); sp.org := org; un := sp;
+//                             INC(org, len) -- increment org by len ?
+               } else if (pieceLen < 0) { // longchar piece
+                       std::cout << "Found LChar piece" << std::endl;
+//                             len := -len; ASSERT(~ODD(len), 100);
+//                             NEW(lp); lp.len := len DIV 2; lp.attr := attr;
+//                             lp.file := rd.rider.Base(); lp.org := org; un := lp;
+//                             INC(org, len) -- increment org by len ?
+               } else { // embedded view
+                       reader.readInt(); reader.readInt();
+                       Store *view = reader.readStore(); // fixme: save somewhere
+//                             NEW(v); v.len := 1; v.attr := attr;
+//                             rd.ReadInt(v.w); rd.ReadInt(v.h); Views.ReadView(rd, v.view);
+//                             v.view.InitContext(NewContext(v, t));
+//                             un := v; INC(org) -- increment org by one?? WTH?
+               }
+               ano = reader.readByte();
+       }
+//             rd.SetPos(org);
+}
+//     PROCEDURE (t: StdModel) Internalize (VAR rd: Stores.Reader);
+//             VAR u, un: Run; sp: Piece; lp: LPiece; v: ViewRef;
+//                     org, len: INTEGER; ano: BYTE; thisVersion: INTEGER;
+//                     attr: Attributes; dict: AttrDict;
+//     BEGIN
+//             ASSERT(t.Domain() = NIL, 20); ASSERT(t.len = 0, 21);
+//             t.Internalize^(rd); IF rd.cancelled THEN RETURN END;
+//             rd.ReadVersion(minVersion, maxStdModelVersion, thisVersion);
+//             IF rd.cancelled THEN RETURN END;
+//             StdInit(t);
+//             dict.len := 0; u := t.trailer;
+//             rd.ReadInt(len); org := rd.Pos() + len;
+//             rd.ReadByte(ano);
+//             WHILE ano # -1 DO
+//                     IF ano = dict.len THEN
+//                             ReadAttr(rd, attr); Stores.Join(t, attr);
+//                             IF dict.len < dictSize THEN dict.attr[dict.len] := attr; INC(dict.len) END
+//                     ELSE
+//                             attr := dict.attr[ano]
+//                     END;
+//                     rd.ReadInt(len);
+//                     IF len > 0 THEN (* piece *)
+//                             NEW(sp); sp.len := len; sp.attr := attr;
+//                             sp.file := rd.rider.Base(); sp.org := org; un := sp;
+//                             INC(org, len)
+//                     ELSIF len < 0 THEN      (* longchar piece *)
+//                             len := -len; ASSERT(~ODD(len), 100);
+//                             NEW(lp); lp.len := len DIV 2; lp.attr := attr;
+//                             lp.file := rd.rider.Base(); lp.org := org; un := lp;
+//                             INC(org, len)
+//                     ELSE    (* len = 0  =>  embedded view *)
+//                             NEW(v); v.len := 1; v.attr := attr;
+//                             rd.ReadInt(v.w); rd.ReadInt(v.h); Views.ReadView(rd, v.view);
+//                             v.view.InitContext(NewContext(v, t));
+//                             un := v; INC(org)
+//                     END;
+//                     INC(t.len, un.len); u.next := un; un.prev := u; u := un;
+//                     rd.ReadByte(ano)
+//             END;
+//             rd.SetPos(org);
+//             u.next := t.trailer; t.trailer.prev := u
+//     END Internalize;
+//
+
+} // namespace odc
diff --git a/textmodel.h b/textmodel.h
new file mode 100644 (file)
index 0000000..13a3d56
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _TEXTMODEL_H_
+#define _TEXTMODEL_H_
+
+#include <oberon.h>
+#include <typeregister.h>
+#include <store.h>
+
+namespace odc {
+
+       class TextModel : public ContainerModel {
+               private:
+               static const std::string TYPENAME;
+               static const TypeProxy<TextModel> PROXY;
+
+               public:
+               TextModel(INTEGER id);
+               static const std::string &getType();
+               static const std::string *getSuper();
+               virtual const std::string &getTypeName() const;
+               virtual void internalize(Reader &reader);
+       };
+
+       class StdTextModel : public TextModel {
+               private:
+               static const std::string TYPENAME;
+               static const TypeProxy<StdTextModel> PROXY;
+
+               public:
+               StdTextModel(INTEGER id);
+               static const std::string &getType();
+               static const std::string *getSuper();
+               virtual const std::string &getTypeName() const;
+               virtual void internalize(Reader &reader);
+       };
+
+} // namespace odc
+
+#endif // _TEXTMODEL_H_