Make all code NULL-free and assert-free
diff --git a/src/harfbuzz-gdef-private.h b/src/harfbuzz-gdef-private.h
index db3ab98..6e0f4e3 100644
--- a/src/harfbuzz-gdef-private.h
+++ b/src/harfbuzz-gdef-private.h
@@ -10,22 +10,34 @@
   static const uint16_t ComponentGlyph		= 0x0004u;
 };
 
-struct AttachPoint;
+/*
+ * Attachment List Table
+ */
+
+struct AttachPoint {
+  /* countour point indices, in increasing numerical order */
+  DEFINE_ARRAY_TYPE (USHORT, pointIndex, pointCount);
+
+  private:
+  USHORT	pointCount;		/* Number of attachment points on
+					 * this glyph */
+  USHORT	pointIndex[];		/* Array of contour point indices--in
+					 * increasing numerical order */
+};
+DEFINE_NULL_ASSERT_SIZE (AttachPoint, 2);
 
 struct AttachList {
-  /* AttachPoint tables, in Coverage Index order */
-  /* TODO get attach lists */
-/*  DEFINE_INDIRECT_OFFSET_ARRAY_TYPE (AttachPoint, attachPoint, glyphCount, get_coverage);
 
-//  get_coverage
-
-  inline Coverage* get_default_language_system (void) {
-    if (!defaultLangSys)
-      return NULL;
-    return (LangSys *)((char*)this + defaultLangSys);
+  inline const AttachPoint* get_attach_points (uint16_t glyph_id) {
+    const Coverage &c = get_coverage ();
+    int c_index = c.get_coverage (glyph_id);
+    return &(*this)[c_index];
   }
 
-*/
+  private:
+  /* AttachPoint tables, in Coverage Index order */
+  DEFINE_OFFSET_ARRAY_TYPE (AttachPoint, attachPoint, glyphCount);
+  DEFINE_ACCESSOR (Coverage, get_coverage, coverage);
 
   private:
   Offset	coverage;		/* Offset to Coverage table -- from
@@ -36,18 +48,7 @@
 					 * tables--from beginning of AttachList
 					 * table--in Coverage Index order */
 };
-ASSERT_SIZE (AttachList, 4);
-
-struct AttachPoint {
-  /* TODO */
-
-  private:
-  USHORT	pointCount;		/* Number of attachment points on
-					 * this glyph */
-  USHORT	pointIndex[];		/* Array of contour point indices--in
-					 * increasing numerical order */
-};
-ASSERT_SIZE (AttachPoint, 2);
+DEFINE_NULL_ASSERT_SIZE (AttachList, 4);
 
 /*
  * Ligature Caret Table
@@ -67,22 +68,7 @@
 					 * LigCaretList table--in Coverage
 					 * Index order */
 };
-ASSERT_SIZE (LigCaretList, 4);
-
-struct LigGlyph {
-  /* Caret value tables, in increasing coordinate order */
-  DEFINE_OFFSET_ARRAY_TYPE (CaretValue, caretValue, caretCount);
-  /* TODO */
-
-  private:
-  USHORT	caretCount;		/* Number of CaretValues for this
-					 * ligature (components - 1) */
-  Offset	caretValue[];		/* Array of offsets to CaretValue
-					 * tables--from beginning of LigGlyph
-					 * table--in increasing coordinate
-					 * order */
-};
-ASSERT_SIZE (LigGlyph, 2);
+DEFINE_NULL_ASSERT_SIZE (LigCaretList, 4);
 
 struct CaretValueFormat1 {
 
@@ -94,7 +80,7 @@
   USHORT	caretValueFormat;	/* Format identifier--format = 1 */
   SHORT		coordinate;		/* X or Y value, in design units */
 };
-ASSERT_SIZE (CaretValueFormat1, 4);
+DEFINE_NULL_ASSERT_SIZE (CaretValueFormat1, 4);
 
 struct CaretValueFormat2 {
 
@@ -106,16 +92,17 @@
   USHORT	caretValueFormat;	/* Format identifier--format = 2 */
   USHORT	caretValuePoint;	/* Contour point index on glyph */
 };
-ASSERT_SIZE (CaretValueFormat2, 4);
+DEFINE_NULL_ASSERT_SIZE (CaretValueFormat2, 4);
 
 struct CaretValueFormat3 {
 
-  inline const Device* get_device (void) const {
-    return (const Device*)((const char*)this + deviceTable);
+  inline const Device& get_device (void) const {
+    if (!deviceTable) return NullDevice;
+    return *(const Device*)((const char*)this + deviceTable);
   }
 
   inline int get_caret_value (int ppem) const {
-    return /* TODO garbage */ (coordinate + get_device()->get_delta (ppem)) / ppem;
+    return /* TODO garbage */ (coordinate + get_device().get_delta (ppem)) / ppem;
   }
 
   private:
@@ -125,7 +112,7 @@
 					 * value--from beginning of CaretValue
 					 * table */
 };
-ASSERT_SIZE (CaretValueFormat3, 6);
+DEFINE_NULL_ASSERT_SIZE (CaretValueFormat3, 6);
 
 struct CaretValue {
   DEFINE_NON_INSTANTIABLE(CaretValue);
@@ -158,16 +145,26 @@
   /* FIXME old HarfBuzz code has a format 4 here! */
   } u;
 };
+DEFINE_NULL (CaretValue, 2);
 
+struct LigGlyph {
+  /* Caret value tables, in increasing coordinate order */
+  DEFINE_OFFSET_ARRAY_TYPE (CaretValue, caretValue, caretCount);
+  /* TODO */
 
-#define DEFINE_ACCESSOR0(const, Type, name, Name) \
-  inline const Type* name (void) const { \
-    if (!Name) return NULL; \
-    return (const Type *)((const char*)this + Name); \
-  }
-#define DEFINE_ACCESSOR(Type, name, Name) \
-	DEFINE_ACCESSOR0(const, Type, name, Name) \
-	DEFINE_ACCESSOR0(     , Type, name, Name)
+  private:
+  USHORT	caretCount;		/* Number of CaretValues for this
+					 * ligature (components - 1) */
+  Offset	caretValue[];		/* Array of offsets to CaretValue
+					 * tables--from beginning of LigGlyph
+					 * table--in increasing coordinate
+					 * order */
+};
+DEFINE_NULL_ASSERT_SIZE (LigGlyph, 2);
+
+/*
+ * GDEF Header
+ */
 
 struct GDEFHeader {
   static const hb_tag_t GDEFTag		= HB_TAG ('G','D','E','F');
@@ -181,18 +178,18 @@
 
   /* Returns 0 if not found. */
   inline int get_glyph_class (uint16_t glyph_id) const {
-    const ClassDef *class_def = get_glyph_class_def ();
-    if (!class_def) return 0;
-    return class_def->get_class (glyph_id);
+    const ClassDef &class_def = get_glyph_class_def ();
+    return class_def.get_class (glyph_id);
   }
 
   /* Returns 0 if not found. */
   inline int get_mark_attachment_type (uint16_t glyph_id) const {
-    const ClassDef *class_def = get_mark_attach_class_def ();
-    if (!class_def) return 0;
-    return class_def->get_class (glyph_id);
+    const ClassDef &class_def = get_mark_attach_class_def ();
+    return class_def.get_class (glyph_id);
   }
 
+  /* TODO get_glyph_property */
+
   /* TODO get_attach and get_lig_caret */
 
   private:
@@ -200,17 +197,17 @@
 					 * 0x00010000 */
   Offset	glyphClassDef;		/* Offset to class definition table
 					 * for glyph type--from beginning of
-					 * GDEF header (may be NULL) */
+					 * GDEF header (may be Null) */
   Offset	attachList;		/* Offset to list of glyphs with
 					 * attachment points--from beginning
-					 * of GDEF header (may be NULL) */
+					 * of GDEF header (may be Null) */
   Offset	ligCaretList;		/* Offset to list of positioning points
 					 * for ligature carets--from beginning
-					 * of GDEF header (may be NULL) */
+					 * of GDEF header (may be Null) */
   Offset	markAttachClassDef;	/* Offset to class definition table for
 					 * mark attachment type--from beginning
-					 * of GDEF header (may be NULL) */
+					 * of GDEF header (may be Null) */
 };
-ASSERT_SIZE (GDEFHeader, 12);
+DEFINE_NULL_ASSERT_SIZE (GDEFHeader, 12);
 
 #endif /* HARFBUZZ_GDEF_PRIVATE_H */
diff --git a/src/harfbuzz-open-private.h b/src/harfbuzz-open-private.h
index 4633ef1..9db3044 100644
--- a/src/harfbuzz-open-private.h
+++ b/src/harfbuzz-open-private.h
@@ -53,12 +53,11 @@
  * as its last item.  An array object is extended with len() and size()
  * methods, as well as overloaded [] operator. */
 #define DEFINE_ARRAY_TYPE(Type, array, num) \
-  DEFINE_INDEX_OPERATOR(const, Type, array, num) \
-  DEFINE_INDEX_OPERATOR(     , Type, array, num) \
+  DEFINE_INDEX_OPERATOR(Type, array, num) \
   DEFINE_LEN_AND_SIZE(Type, array, num)
-#define DEFINE_INDEX_OPERATOR(const, Type, array, num) \
+#define DEFINE_INDEX_OPERATOR(Type, array, num) \
   inline const Type& operator[] (unsigned int i) const { \
-    assert (i < num); \
+    if (i >= num) return Null##Type; \
     return array[i]; \
   }
 
@@ -66,34 +65,42 @@
  * of offsets to the objects, relative to the beginning of the current
  * object. */
 #define DEFINE_OFFSET_ARRAY_TYPE(Type, array, num) \
-  DEFINE_OFFSET_INDEX_OPERATOR(const, Type, array, num) \
-  DEFINE_OFFSET_INDEX_OPERATOR(     , Type, array, num) \
+  DEFINE_OFFSET_INDEX_OPERATOR(Type, array, num) \
   DEFINE_LEN_AND_SIZE(Offset, array, num)
-#define DEFINE_OFFSET_INDEX_OPERATOR(const, Type, array, num) \
+#define DEFINE_OFFSET_INDEX_OPERATOR(Type, array, num) \
   inline const Type& operator[] (unsigned int i) const { \
-    assert (i < num); \
-    assert (array[i]); /* TODO: should just skip them */ \
+    if (i >= num) return Null##Type; \
+    if (!array[i]) return Null##Type; \
     return *(const Type *)((const char*)this + array[i]); \
   }
 
 #define DEFINE_RECORD_ARRAY_TYPE(Type, array, num) \
-  DEFINE_RECORD_ACCESSOR(const, Type, array, num) \
-  DEFINE_RECORD_ACCESSOR(     , Type, array, num) \
+  DEFINE_RECORD_ACCESSOR(Type, array, num) \
   DEFINE_LEN_AND_SIZE(Record, array, num)
-#define DEFINE_RECORD_ACCESSOR(const, Type, array, num) \
+#define DEFINE_RECORD_ACCESSOR(Type, array, num) \
   inline const Type& operator[] (unsigned int i) const { \
-    assert (i < num); \
-    assert (array[i].offset); /* TODO: should just skip them */ \
+    if (i >= num) return Null##Type; \
+    if (!array[i].offset) return Null##Type; \
     return *(const Type *)((const char*)this + array[i].offset); \
   } \
   inline const Tag& get_tag (unsigned int i) const { \
-    assert (i < num); \
+    if (i >= num) return NullTag; \
     return array[i].tag; \
   } \
   /* TODO: implement find_tag() */
 
+/*
+ * List types
+ */
 
-
+#define DEFINE_LIST_ACCESSOR(Type, name) \
+  inline const Type##List& get_##name##_list (void) const { \
+    if (!name##List) return Null##Type##List; \
+    return *(const Type##List *)((const char*)this + name##List); \
+  } \
+  inline const Type& get_##name (unsigned int i) const { \
+    return get_##name##_list()[i]; \
+  }
 
 /*
  * Class features
@@ -105,6 +112,20 @@
   private: inline Type() {} /* cannot be instantiated */ \
   public:
 
+/* defines Null##Type as a safe nil instance of Type */
+#define DEFINE_NULL_DATA(Type, size, data) \
+  static const unsigned char Null##Type##Data[size] = data; \
+  DEFINE_NULL_ALIAS (Type, Type)
+#define DEFINE_NULL(Type, size) \
+	DEFINE_NULL_DATA(Type, size, "")
+#define DEFINE_NULL_ASSERT_SIZE(Type, size) \
+	DEFINE_NULL_ASSERT_SIZE_DATA(Type, size, "")
+#define DEFINE_NULL_ASSERT_SIZE_DATA(Type, size, data) \
+  ASSERT_SIZE (Type, size); \
+  DEFINE_NULL_DATA (Type, size, data)
+#define DEFINE_NULL_ALIAS(NewType, OldType) \
+  static const NewType &Null##NewType = *(NewType *)Null##OldType##Data
+
 /* get_for_data() is a static class method returning a reference to an
  * instance of Type located at the input data location.  It's just a
  * fancy cast! */
@@ -117,6 +138,13 @@
 	STATIC_DEFINE_GET_FOR_DATA0(     , Type)
 
 
+#define DEFINE_ACCESSOR(Type, name, Name) \
+  inline const Type& name (void) const { \
+    if (!Name) return Null##Type; \
+    return *(const Type*)((const char*)this + Name); \
+  }
+
+
 
 /*
  *
@@ -136,17 +164,17 @@
 
 
 DEFINE_INT_TYPE_STRUCT (BYTE,	 u,  8);	/*  8-bit unsigned integer. */
-ASSERT_SIZE (BYTE, 1);
+DEFINE_NULL_ASSERT_SIZE (BYTE, 1);
 DEFINE_INT_TYPE_STRUCT (CHAR,	  ,  8);	/*  8-bit signed integer. */
-ASSERT_SIZE (CHAR, 1);
+DEFINE_NULL_ASSERT_SIZE (CHAR, 1);
 DEFINE_INT_TYPE_STRUCT (USHORT,  u, 16);	/* 16-bit unsigned integer. */
-ASSERT_SIZE (USHORT, 2);
+DEFINE_NULL_ASSERT_SIZE (USHORT, 2);
 DEFINE_INT_TYPE_STRUCT (SHORT,	  , 16);	/* 16-bit signed integer. */
-ASSERT_SIZE (SHORT, 2);
+DEFINE_NULL_ASSERT_SIZE (SHORT, 2);
 DEFINE_INT_TYPE_STRUCT (ULONG,	 u, 32);	/* 32-bit unsigned integer. */
-ASSERT_SIZE (ULONG, 4);
+DEFINE_NULL_ASSERT_SIZE (ULONG, 4);
 DEFINE_INT_TYPE_STRUCT (LONG,	  , 32);	/* 32-bit signed integer. */
-ASSERT_SIZE (LONG, 4);
+DEFINE_NULL_ASSERT_SIZE (LONG, 4);
 
 /* Date represented in number of seconds since 12:00 midnight, January 1,
  * 1904. The value is represented as a signed 64-bit integer. */
@@ -166,7 +194,7 @@
   SHORT i;
   USHORT f;
 };
-ASSERT_SIZE (Fixed, 4);
+DEFINE_NULL_ASSERT_SIZE (Fixed, 4);
 
 /* Smallest measurable distance in the em space. */
 struct FUNIT;
@@ -174,18 +202,18 @@
 /* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */
 struct FWORD : SHORT {
 };
-ASSERT_SIZE (FWORD, 2);
+DEFINE_NULL_ASSERT_SIZE (FWORD, 2);
 
 /* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
 struct UFWORD : USHORT {
 };
-ASSERT_SIZE (UFWORD, 2);
+DEFINE_NULL_ASSERT_SIZE (UFWORD, 2);
 
 /* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
 struct F2DOT14 : SHORT {
   inline operator double() const { return (uint32_t) this / 16384.; }
 };
-ASSERT_SIZE (F2DOT14, 2);
+DEFINE_NULL_ASSERT_SIZE (F2DOT14, 2);
 
 /* Array of four uint8s (length = 32 bits) used to identify a script, language
  * system, feature, or baseline */
@@ -205,14 +233,15 @@
   char v[4];
 };
 ASSERT_SIZE (Tag, 4);
+DEFINE_NULL_DATA (Tag, 5, "    ");
 
 /* Glyph index number, same as uint16 (length = 16 bits) */
 DEFINE_INT_TYPE_STRUCT (GlyphID, u, 16);
-ASSERT_SIZE (GlyphID, 2);
+DEFINE_NULL_ASSERT_SIZE (GlyphID, 2);
 
-/* Offset to a table, same as uint16 (length = 16 bits), NULL offset = 0x0000 */
+/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */
 DEFINE_INT_TYPE_STRUCT (Offset, u, 16);
-ASSERT_SIZE (Offset, 2);
+DEFINE_NULL_ASSERT_SIZE (Offset, 2);
 
 /* CheckSum */
 struct CheckSum : ULONG {
@@ -225,7 +254,7 @@
     return Sum;
   }
 };
-ASSERT_SIZE (CheckSum, 4);
+DEFINE_NULL_ASSERT_SIZE (CheckSum, 4);
 
 
 /*
@@ -234,13 +263,13 @@
 
 struct USHORT_Version : USHORT {
 };
-ASSERT_SIZE (USHORT_Version, 2);
+DEFINE_NULL_ASSERT_SIZE (USHORT_Version, 2);
 
 struct Fixed_Version : Fixed {
   inline int16_t major (void) const { return this->int_part(); }
   inline int16_t minor (void) const { return this->frac_part(); }
 };
-ASSERT_SIZE (Fixed_Version, 4);
+DEFINE_NULL_ASSERT_SIZE (Fixed_Version, 4);
 
 
 /*
@@ -267,7 +296,7 @@
 				 * file. */
   ULONG		length;		/* Length of this table. */
 } OpenTypeTable;
-ASSERT_SIZE (TableDirectory, 16);
+DEFINE_NULL_ASSERT_SIZE (TableDirectory, 16);
 
 typedef struct OffsetTable {
   /* OpenTypeTables, in no particular order */
@@ -282,7 +311,8 @@
   USHORT	rangeShift;	/* NumTables x 16-searchRange. */
   TableDirectory tableDir[];	/* TableDirectory entries. numTables items */
 } OpenTypeFontFace;
-ASSERT_SIZE (OffsetTable, 12);
+DEFINE_NULL_ASSERT_SIZE (OffsetTable, 12);
+DEFINE_NULL_ALIAS (OpenTypeFontFace, OffsetTable);
 
 /*
  * TrueType Collections
@@ -300,7 +330,7 @@
   ULONG	offsetTable[];	/* Array of offsets to the OffsetTable for each font
 			 * from the beginning of the file */
 };
-ASSERT_SIZE (TTCHeader, 12);
+DEFINE_NULL_ASSERT_SIZE (TTCHeader, 12);
 
 
 /*
@@ -338,25 +368,18 @@
     }
   }
   inline const OpenTypeFontFace& operator[] (unsigned int i) const {
-    assert (i < get_len ());
+    if (i >= get_len ()) return NullOpenTypeFontFace;
     switch (tag) {
     default: case TrueTypeTag: case CFFTag: return (const OffsetTable&)*this;
     case TTCTag: return ((const TTCHeader&)*this)[i];
     }
   }
-  inline OpenTypeFontFace& operator[] (unsigned int i) {
-    assert (i < get_len ());
-    switch (tag) {
-    default: case TrueTypeTag: case CFFTag: return (OffsetTable&)*this;
-    case TTCTag: return ((TTCHeader&)*this)[i];
-    }
-  }
   inline const Tag& get_tag (void) const { return tag; }
 
   private:
   Tag		tag;		/* 4-byte identifier. */
 };
-ASSERT_SIZE (OpenTypeFontFile, 4);
+DEFINE_NULL_ASSERT_SIZE (OpenTypeFontFile, 4);
 
 
 
@@ -370,59 +393,12 @@
  * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
  */
 
-struct Script;
-struct ScriptList;
-struct LangSys;
-struct Feature;
-struct FeatureList;
-struct Lookup;
-struct LookupList;
-
 typedef struct Record {
   Tag		tag;		/* 4-byte Tag identifier */
   Offset	offset;		/* Offset from beginning of object holding
 				 * the Record */
 } ScriptRecord, LangSysRecord, FeatureRecord;
-ASSERT_SIZE (Record, 6);
-
-struct ScriptList {
-  /* Scripts, in sorted alphabetical tag order */
-  DEFINE_RECORD_ARRAY_TYPE (Script, scriptRecord, scriptCount);
-
-  private:
-  USHORT	scriptCount;	/* Number of ScriptRecords */
-  ScriptRecord	scriptRecord[]; /* Array of ScriptRecords--listed alphabetically
-				 * by ScriptTag */
-};
-ASSERT_SIZE (ScriptList, 2);
-
-struct Script {
-  /* LangSys', in sorted alphabetical tag order */
-  DEFINE_RECORD_ARRAY_TYPE (LangSys, langSysRecord, langSysCount);
-
-  /* Return NULL if none */
-  inline const LangSys* get_default_language_system (void) const {
-    if (!defaultLangSys)
-      return NULL;
-    return (const LangSys *)((const char*)this + defaultLangSys);
-  }
-  inline LangSys* get_default_language_system (void) {
-    if (!defaultLangSys)
-      return NULL;
-    return (LangSys *)((char*)this + defaultLangSys);
-  }
-
-  /* TODO implement find_language_system based on find_tag */
-
-  private:
-  Offset	defaultLangSys;	/* Offset to DefaultLangSys table--from
-				 * beginning of Script table--may be NULL */
-  USHORT	langSysCount;	/* Number of LangSysRecords for this script--
-				 * excluding the DefaultLangSys */
-  LangSysRecord	langSysRecord[];/* Array of LangSysRecords--listed
-				 * alphabetically by LangSysTag */
-};
-ASSERT_SIZE (Script, 4);
+DEFINE_NULL_ASSERT_SIZE (Record, 6);
 
 struct LangSys {
   /* Feature indices, in no particular order */
@@ -438,7 +414,7 @@
   /* TODO implement find_feature */
 
   private:
-  Offset	lookupOrder;	/* = NULL (reserved for an offset to a
+  Offset	lookupOrder;	/* = Null (reserved for an offset to a
 				 * reordering table) */
   USHORT	reqFeatureIndex;/* Index of a feature required for this
 				 * language system--if no required features
@@ -449,7 +425,60 @@
   USHORT	featureIndex[];	/* Array of indices into the FeatureList--in
 				 * arbitrary order. featureCount entires long */
 };
-ASSERT_SIZE (LangSys, 6);
+DEFINE_NULL_ASSERT_SIZE_DATA (LangSys, 6, "\0\0\xFF\xFF");
+
+struct Script {
+  /* LangSys', in sorted alphabetical tag order */
+  DEFINE_RECORD_ARRAY_TYPE (LangSys, langSysRecord, langSysCount);
+
+  inline const bool has_default_language_system (void) const {
+    return defaultLangSys != 0;
+  }
+  inline const LangSys& get_default_language_system (void) const {
+    if (!defaultLangSys)
+      return NullLangSys;
+    return *(LangSys*)((const char*)this + defaultLangSys);
+  }
+
+  /* TODO implement find_language_system based on find_tag */
+
+  private:
+  Offset	defaultLangSys;	/* Offset to DefaultLangSys table--from
+				 * beginning of Script table--may be Null */
+  USHORT	langSysCount;	/* Number of LangSysRecords for this script--
+				 * excluding the DefaultLangSys */
+  LangSysRecord	langSysRecord[];/* Array of LangSysRecords--listed
+				 * alphabetically by LangSysTag */
+};
+DEFINE_NULL_ASSERT_SIZE (Script, 4);
+
+struct ScriptList {
+  /* Scripts, in sorted alphabetical tag order */
+  DEFINE_RECORD_ARRAY_TYPE (Script, scriptRecord, scriptCount);
+
+private:
+  USHORT	scriptCount;	/* Number of ScriptRecords */
+  ScriptRecord	scriptRecord[]; /* Array of ScriptRecords--listed alphabetically
+				 * by ScriptTag */
+};
+DEFINE_NULL_ASSERT_SIZE (ScriptList, 2);
+
+struct Feature {
+  /* LookupList indices, in no particular order */
+  DEFINE_ARRAY_TYPE (USHORT, lookupIndex, lookupCount);
+
+  private:
+  Offset	featureParams;	/* Offset to Feature Parameters table (if one
+				 * has been defined for the feature), relative
+				 * to the beginning of the Feature Table; = Null 
+				 * if not required */
+  USHORT	lookupCount;	/* Number of LookupList indices for this
+				 * feature */
+  USHORT	lookupIndex[];	/* Array of LookupList indices for this
+				 * feature--zero-based (first lookup is
+				 * LookupListIndex = 0) */
+};
+DEFINE_NULL_ASSERT_SIZE (Feature, 4);
 
 struct FeatureList {
   /* Feature indices, in sorted alphabetical tag order */
@@ -461,38 +490,7 @@
 				 * feature has FeatureIndex = 0)--listed
 				 * alphabetically by FeatureTag */
 };
-ASSERT_SIZE (FeatureList, 2);
-
-struct Feature {
-  /* LookupList indices, in no particular order */
-  DEFINE_ARRAY_TYPE (USHORT, lookupIndex, lookupCount);
-
-  // TODO: implement get_feature_params()
-
-  private:
-  Offset	featureParams;	/* Offset to Feature Parameters table (if one
-				 * has been defined for the feature), relative
-				 * to the beginning of the Feature Table; = NULL
-				 * if not required */
-  USHORT	lookupCount;	/* Number of LookupList indices for this
-				 * feature */
-  USHORT	lookupIndex[];	/* Array of LookupList indices for this
-				 * feature--zero-based (first lookup is
-				 * LookupListIndex = 0) */
-};
-ASSERT_SIZE (Feature, 4);
-
-struct LookupList {
-  /* Lookup indices, in sorted alphabetical tag order */
-  DEFINE_OFFSET_ARRAY_TYPE (Lookup, lookupOffset, lookupCount);
-
-  private:
-  USHORT	lookupCount;	/* Number of lookups in this table */
-  Offset	lookupOffset[];	/* Array of offsets to Lookup tables--from
-				 * beginning of LookupList--zero based (first
-				 * lookup is Lookup index = 0) */
-};
-ASSERT_SIZE (LookupList, 2);
+DEFINE_NULL_ASSERT_SIZE (FeatureList, 2);
 
 struct LookupFlag : USHORT {
   static const uint16_t RightToLeft		= 0x0001u;
@@ -502,11 +500,20 @@
   static const uint16_t Reserved		= 0x00F0u;
   static const uint16_t MarkAttachmentType	= 0xFF00u;
 };
-ASSERT_SIZE (LookupFlag, 2);
+DEFINE_NULL_ASSERT_SIZE (LookupFlag, 2);
+
+struct LookupSubTable {
+  DEFINE_NON_INSTANTIABLE(LookupSubTable);
+
+  private:
+  USHORT	format;		/* Subtable format.  Different for GSUB and GPOS */
+};
+DEFINE_NULL_ASSERT_SIZE (LookupSubTable, 2);
+
 
 struct Lookup {
   /* SubTables, in the desired order */
-  DEFINE_OFFSET_ARRAY_TYPE (char*, subTableOffset, subTableCount);
+  DEFINE_OFFSET_ARRAY_TYPE (LookupSubTable, subTableOffset, subTableCount);
 
   inline bool is_right_to_left	(void) const { return lookupFlag & LookupFlag::RightToLeft; }
   inline bool ignore_base_glyphs(void) const { return lookupFlag & LookupFlag::IgnoreBaseGlyphs; }
@@ -524,7 +531,19 @@
   Offset	subTableOffset[];/* Array of offsets to SubTables-from
 				  * beginning of Lookup table */
 };
-ASSERT_SIZE (Lookup, 6);
+DEFINE_NULL_ASSERT_SIZE (Lookup, 6);
+
+struct LookupList {
+  /* Lookup indices, in sorted alphabetical tag order */
+  DEFINE_OFFSET_ARRAY_TYPE (Lookup, lookupOffset, lookupCount);
+
+  private:
+  USHORT	lookupCount;	/* Number of lookups in this table */
+  Offset	lookupOffset[];	/* Array of offsets to Lookup tables--from
+				 * beginning of LookupList--zero based (first
+				 * lookup is Lookup index = 0) */
+};
+DEFINE_NULL_ASSERT_SIZE (LookupList, 2);
 
 /*
  * Coverage Table
@@ -565,7 +584,7 @@
   USHORT	startCoverageIndex;	/* Coverage Index of first GlyphID in
 					 * range */
 };
-ASSERT_SIZE (CoverageRangeRecord, 6);
+DEFINE_NULL_ASSERT_SIZE_DATA (CoverageRangeRecord, 6, "\001");
 
 struct CoverageFormat2 {
   /* CoverageRangeRecords, in sorted numerical start order */
@@ -617,6 +636,7 @@
   CoverageFormat2	format2;
   } u;
 };
+DEFINE_NULL (Coverage, 2);
 
 /*
  * Class Definition Table
@@ -653,7 +673,7 @@
   GlyphID	end;		/* Last GlyphID in the range */
   USHORT	classValue;	/* Applied to all glyphs in the range */
 };
-ASSERT_SIZE (ClassRangeRecord, 6);
+DEFINE_NULL_ASSERT_SIZE_DATA (ClassRangeRecord, 6, "\001");
 
 struct ClassDefFormat2 {
   /* ClassRangeRecords, in sorted numerical start order */
@@ -704,6 +724,7 @@
   ClassDefFormat2	format2;
   } u;
 };
+DEFINE_NULL (ClassDef, 2);
 
 /*
  * Device Tables
@@ -748,23 +769,13 @@
   USHORT	deltaFormat;	/* Format of DeltaValue array data: 1, 2, or 3 */
   USHORT	deltaValue[];	/* Array of compressed data */
 };
-ASSERT_SIZE (Device, 6);
+DEFINE_NULL_ASSERT_SIZE (Device, 6);
 
+/*
+ * GSUB/GPOS Header
+ */
 
-
-#define DEFINE_LIST_ACCESSOR0(const, Type, name) \
-  inline const Type##List* get_##name##_list (void) const { \
-    assert (name##List); \
-    return (const Type##List *)((const char*)this + name##List); \
-  } \
-  inline const Type& get_##name (unsigned int i) const { \
-    return (*get_##name##_list())[i]; \
-  }
-#define DEFINE_LIST_ACCESSOR(Type, name) \
-	DEFINE_LIST_ACCESSOR0(const, Type, name) \
-	DEFINE_LIST_ACCESSOR0(     , Type, name)
-
-struct GSUBGPOSHeader {
+typedef struct GSUBGPOSHeader {
   static const hb_tag_t GSUBTag		= HB_TAG ('G','S','U','B');
   static const hb_tag_t GPOSTag		= HB_TAG ('G','P','O','S');
 
@@ -785,7 +796,9 @@
 				 * GSUB/GPOS table */
   Offset	lookupList; 	/* Offset to LookupList table--from beginning of
 				 * GSUB/GPOS table */
-};
-ASSERT_SIZE (GSUBGPOSHeader, 10);
+} GSUBHeader, GPOSHeader;
+DEFINE_NULL_ASSERT_SIZE (GSUBGPOSHeader, 10);
+DEFINE_NULL_ALIAS (GSUBHeader, GSUBGPOSHeader);
+DEFINE_NULL_ALIAS (GPOSHeader, GSUBGPOSHeader);
 
 #endif /* HARFBUZZ_OPEN_PRIVATE_H */
diff --git a/src/main.cc b/src/main.cc
index 313723e..3654e5e 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -51,7 +51,7 @@
       if (table.get_tag() == "GSUB" || table.get_tag() == "GPOS") {
         const GSUBGPOSHeader &g = GSUBGPOSHeader::get_for_data (ot[table]);
 
-	const ScriptList &scripts = *g.get_script_list();
+	const ScriptList &scripts = g.get_script_list();
 	int num_scripts = scripts.get_len ();
 	printf ("    %d script(s) found in table\n", num_scripts);
 	for (int n_script = 0; n_script < num_scripts; n_script++) {
@@ -59,7 +59,7 @@
 	  printf ("    Script %2d of %2d: %.4s\n", n_script+1, num_scripts,
 	          (const char *)scripts.get_tag(n_script));
 
-	  if (script.get_default_language_system () == NULL)
+	  if (!script.has_default_language_system())
 	    printf ("      No default language system\n");
 	  int num_langsys = script.get_len ();
 	  printf ("      %d language system(s) found in script\n", num_langsys);
@@ -73,7 +73,7 @@
 	  }
 	}
         
-	const FeatureList &features = *g.get_feature_list();
+	const FeatureList &features = g.get_feature_list();
 	int num_features = features.get_len ();
 	printf ("    %d feature(s) found in table\n", num_features);
 	for (int n_feature = 0; n_feature < num_features; n_feature++) {
@@ -83,7 +83,7 @@
 		  feature.get_len());
 	}
         
-	const LookupList &lookups = *g.get_lookup_list();
+	const LookupList &lookups = g.get_lookup_list();
 	int num_lookups = lookups.get_len ();
 	printf ("    %d lookup(s) found in table\n", num_lookups);
 	for (int n_lookup = 0; n_lookup < num_lookups; n_lookup++) {