Include <sys/types.h> and "config.h".
[m17n/libotf.git] / example / otfdump.c
index 18d0a53..3ec19e0 100644 (file)
@@ -1,13 +1,34 @@
+/* otfdump.c -- Dump OpenType Layout Tables.
+
+Copyright (C) 2003, 2004
+  National Institute of Advanced Industrial Science and Technology (AIST)
+  Registration Number H15PRO167
+
+This file is part of libotf.
+
+Libotf is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as published
+by the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+Libotf is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library, in a file named COPYING; if not,
+write to the Free Software Foundation, Inc., 59 Temple Place, Suite
+330, Boston, MA 02111-1307, USA.  */
+
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
-
-extern int EF_ALIGNMENT;
-extern int EF_PROTECT_BELOW;
-extern int EF_PROTECT_FREE;
+#include <libgen.h>
 
 #include <otf.h>
 
@@ -77,35 +98,42 @@ dump_head_table (int indent, OTF_head *head)
 /* COMMON */
 
 static void
-dump_glyph_ids (OTF_GlyphID *ids, unsigned num)
+dump_glyph_ids (int indent, char *title, OTF_GlyphID *ids, unsigned count)
 {
-  while (num-- > 0)
+  IPRINT ("(%s (count %d)", title, count);
+  while (count-- > 0)
     {
       printf (" #x%04X", *ids);
       ids++;
     }
+  printf (")");
 }
 
-static void
+static int *
 dump_coverage (int indent, char *title, OTF_Coverage *coverage)
 {
   int i;
+  int *char_list;
 
   IPRINT ("(%sCoverage (CoverageFormat %d)",
          (title ? title : ""), coverage->CoverageFormat);
   indent++;
   if (coverage->CoverageFormat == 1)
     {
-      IPRINT ("(GlyphCount %d)", coverage->Count);
-      IPRINT ("(GlyphArray");
-      dump_glyph_ids (coverage->table.GlyphArray, coverage->Count);
-      printf (")");
+      dump_glyph_ids (indent, "GlyphArray", coverage->table.GlyphArray,
+                     coverage->Count);
+      char_list = malloc (sizeof (int) * (coverage->Count + 1));
+      for (i = 0; i < coverage->Count; i++)
+       char_list[i] = coverage->table.GlyphArray[i];
+      char_list[i] = -1;
     }
   else
     {
+      int n, c;
+
       IPRINT ("(RangeCount %d)", coverage->Count);
       indent++;
-      for (i = 0; i < coverage->Count; i++)
+      for (i = n = 0; i < coverage->Count; i++)
        {
          IPRINT ("(Range (%d) (Start #x%04X) (End #x%04X)", i,
                  coverage->table.RangeRecord[i].Start,
@@ -114,9 +142,19 @@ dump_coverage (int indent, char *title, OTF_Coverage *coverage)
          IPRINT ("(StartCoverageIndex %d))",
                  coverage->table.RangeRecord[i].StartCoverageIndex);
          indent--;
+         n += (coverage->table.RangeRecord[i].End
+               - coverage->table.RangeRecord[i].Start + 1);
        }
+      char_list = malloc (sizeof (int) * (n + 1));
+      for (i = n = 0; i < coverage->Count; i++)
+       for (c = coverage->table.RangeRecord[i].Start;
+            c <= coverage->table.RangeRecord[i].End;
+            c++)
+         char_list[n++] = c;
+      char_list[n] = -1;
     }
   printf (")");
+  return char_list;
 }
 
 static void
@@ -127,7 +165,7 @@ dump_coverage_list (int indent, char *title,
 
   IPRINT ("(%s %d)", title, num);
   for (i = 0; i < num; i++)
-    dump_coverage (indent, NULL, coverage + i);
+    free (dump_coverage (indent, NULL, coverage + i));
 }
 
 
@@ -227,32 +265,33 @@ dump_class_def (int indent, char *title, OTF_ClassDef *class)
   IPRINT ("(%s (offset #x%04X) (ClassFormat %d)",
          (title ? title : "ClassDef"),
          class->offset, class->ClassFormat);
-  indent++;
-  if (class->ClassFormat == 1)
-    {
-      IPRINT ("(StartGlyph #x%04X)", class->f.f1.StartGlyph);
-      IPRINT ("(GlyphCount %d)", class->f.f1.GlyphCount);
-      IPRINT ("(ClassValueArray");
-      dump_glyph_ids ((OTF_GlyphID *) class->f.f1.ClassValueArray,
-                     class->f.f1.GlyphCount);
-      printf (")");
-    }
-  else if (class->ClassFormat == 2)
+  if (class->offset)
     {
-      int i;
-
-      IPRINT ("(ClassRangeCount %d)", class->f.f2.ClassRangeCount);
-      IPRINT ("(ClassRangeRecord");
       indent++;
-      for (i = 0; i < class->f.f2.ClassRangeCount; i++)
-       IPRINT ("((Start #x%04X) (End #x%04X) (class %d))",
-               class->f.f2.ClassRangeRecord[i].Start,
-               class->f.f2.ClassRangeRecord[i].End,
-               class->f.f2.ClassRangeRecord[i].Class);
-      printf (")");
+      if (class->ClassFormat == 1)
+       {
+         IPRINT ("(StartGlyph #x%04X)", class->f.f1.StartGlyph);
+         dump_glyph_ids (indent, "ClassValueArray",
+                         (OTF_GlyphID *) class->f.f1.ClassValueArray,
+                         class->f.f1.GlyphCount);
+       }
+      else if (class->ClassFormat == 2)
+       {
+         int i;
+
+         IPRINT ("(ClassRangeCount %d)", class->f.f2.ClassRangeCount);
+         IPRINT ("(ClassRangeRecord");
+         indent++;
+         for (i = 0; i < class->f.f2.ClassRangeCount; i++)
+           IPRINT ("((Start #x%04X) (End #x%04X) (class %d))",
+                   class->f.f2.ClassRangeRecord[i].Start,
+                   class->f.f2.ClassRangeRecord[i].End,
+                   class->f.f2.ClassRangeRecord[i].Class);
+         printf (")");
+       }
+      else
+       printf (" UnknownClassFormat");
     }
-  else
-    printf ("UknownClassFormat");
   printf (")");
 }
 
@@ -303,19 +342,34 @@ dump_sequence_list (int indent, OTF_Sequence *sequence, unsigned num)
     {
       IPRINT ("(Sequence (%d) (offset #x%04X)",
              i, sequence[i].offset);
-      indent++;
-      IPRINT ("(GlyphCount %d)", sequence[i].GlyphCount);
-      IPRINT ("(Substitute");
-      dump_glyph_ids (sequence[i].Substitute, sequence[i].GlyphCount);
-      printf ("))");
-      indent--;
+      dump_glyph_ids (indent + 1, "Substitute", sequence[i].Substitute,
+                     sequence[i].GlyphCount);
+      printf (")");
     }
 }
 
 static void
-dump_ligature_set_list (int indent, OTF_LigatureSet *ligset, unsigned num)
+dump_alternate_set_list (int indent, OTF_AlternateSet *altset, unsigned num)
 {
-  int i, j;
+  int i;
+
+  IPRINT ("(AlternateSetCount %d)", num);
+  for (i = 0; i < num; i++)
+    {
+      IPRINT ("(AlternateSet (%d) (offset #x%04X)",
+             i, altset[i].offset);
+      dump_glyph_ids (indent + 1, "Alternate", altset[i].Alternate,
+                     altset[i].GlyphCount);
+      printf (")");
+    }
+}
+
+
+static void
+dump_ligature_set_list (int indent, int *char_list,
+                       OTF_LigatureSet *ligset, unsigned num)
+{
+  int i, j, k;
 
   IPRINT ("(LigSetCount %d)", num);
   for (i = 0; i < num; i++)
@@ -330,12 +384,13 @@ dump_ligature_set_list (int indent, OTF_LigatureSet *ligset, unsigned num)
          indent++;
          IPRINT ("(LigGlyph #x%04X)",
                  ligset[i].Ligature[j].LigGlyph);
-         IPRINT ("(ComCount %d)",
-                 ligset[i].Ligature[j].CompCount);
-         IPRINT ("(Component");
-         dump_glyph_ids (ligset[i].Ligature[j].Component,
+         dump_glyph_ids (indent, "Component", ligset[i].Ligature[j].Component,
                          ligset[i].Ligature[j].CompCount - 1);
-         printf ("))");
+         IPRINT ("(i.e. #x%04X", char_list[i]);
+         for (k = 0; k < ligset[i].Ligature[j].CompCount - 1; k++)
+           printf (" #x%04X", ligset[i].Ligature[j].Component[k]);
+         printf (" = #x%04X)", ligset[i].Ligature[j].LigGlyph);
+         printf (")");
          indent--;
        }
       indent--;
@@ -344,6 +399,33 @@ dump_ligature_set_list (int indent, OTF_LigatureSet *ligset, unsigned num)
 }
 
 static void
+dump_pair_set_list (int indent, unsigned count, OTF_PairSet *set)
+{
+  int i, j;
+
+  for (i = 0; i < count; i++)
+    {
+      IPRINT ("(PairSet (%d)", i);
+      indent++;
+      for (j = 0; j < set[i].PairValueCount; j++)
+       {
+         IPRINT ("(PairValueRecord (%d)", j);
+         indent++;
+         IPRINT ("(SecondGlyph #x%04X)",
+                 set[i].PairValueRecord[j].SecondGlyph);
+         dump_value_record (indent, "Value1",
+                            &set[i].PairValueRecord[j].Value1);
+         dump_value_record (indent, "Value2",
+                            &set[i].PairValueRecord[j].Value2);
+         printf (")");
+         indent--;
+       }
+      printf (")");
+      indent--;
+    }
+}
+
+static void
 dump_class1_record_list (int indent,
                         unsigned Class1Count, unsigned Class2Count,
                         OTF_Class1Record *rec)
@@ -389,6 +471,22 @@ dump_anchor (int indent, OTF_Anchor *anchor)
 }
 
 static void
+dump_entry_exit_list (int indent, unsigned count, OTF_EntryExitRecord *rec)
+{
+  int i;
+
+  for (i = 0; i < count; i++)
+    {
+      IPRINT ("(EntryExitRecord (%d)", i);
+      indent++;
+      dump_anchor (indent, &rec[i].EntryAnchor);
+      dump_anchor (indent, &rec[i].EntryAnchor);
+      printf (")");
+      indent--;
+    }
+}
+
+static void
 dump_mark_array (int indent, OTF_MarkArray *array)
 {
   int i;
@@ -405,17 +503,17 @@ dump_mark_array (int indent, OTF_MarkArray *array)
 }
 
 static void
-dump_base_array (int indent, unsigned ClassCount, OTF_BaseArray *array)
+dump_anchor_array (int indent, unsigned ClassCount, OTF_AnchorArray *array)
 {
   int i, j;
 
-  IPRINT ("(BaseArray (BaseCount %d)", array->BaseCount);
+  IPRINT ("(AnchorArray (Count %d)", array->Count);
   indent++;
-  for (i = 0; i < array->BaseCount; i++)
+  for (i = 0; i < array->Count; i++)
     {
-      IPRINT ("(BaseRecord (%d) ", i);
+      IPRINT ("(AnchorRecord (%d) ", i);
       for (j = 0; j < ClassCount; j++)
-       dump_anchor (indent + 1, array->BaseRecord[i].BaseAnchor + j);
+       dump_anchor (indent + 1, array->AnchorRecord[i].Anchor + j);
       printf (")");
     }
   printf (")");
@@ -423,15 +521,14 @@ dump_base_array (int indent, unsigned ClassCount, OTF_BaseArray *array)
 
 
 static void
-dump_subst_lookup_record_list (int indent,
-                              OTF_SubstLookupRecord *rec, unsigned num)
+dump_lookup_record_list (int indent, OTF_LookupRecord *rec, unsigned num)
 {
   int i;
 
-  IPRINT ("(SubstCount %d)", num);
+  IPRINT ("(LookupCount %d)", num);
   for (i = 0; i < num; i++)
     {
-      IPRINT ("(SubstLookupRecord (%d)", i);
+      IPRINT ("(LookupRecord (%d)", i);
       indent++;
       IPRINT ("(SequenceIndex %d)", rec[i].SequenceIndex);
       IPRINT ("(LookupListIndex %d))", rec[i].LookupListIndex);
@@ -441,9 +538,9 @@ dump_subst_lookup_record_list (int indent,
 
 
 static void dump_lookup_subtable_gsub (int indent, int index, unsigned type,
-                                      OTF_LookupSubTable *subtable);
+                                      OTF_LookupSubTableGSUB *subtable);
 static void dump_lookup_subtable_gpos (int indent, int index, unsigned type,
-                                      OTF_LookupSubTable *subtable);
+                                      OTF_LookupSubTableGPOS *subtable);
 
 
 static void
@@ -464,24 +561,174 @@ dump_lookup_list (int indent, OTF_LookupList *list, int gsub)
       if (gsub)
        for (j = 0; j < lookup->SubTableCount; j++)
          dump_lookup_subtable_gsub (indent + 1, j,
-                                    lookup->LookupType, lookup->SubTable + j);
+                                    lookup->LookupType,
+                                    lookup->SubTable.gsub + j);
       else
        for (j = 0; j < lookup->SubTableCount; j++)
          dump_lookup_subtable_gpos (indent + 1, j,
-                                    lookup->LookupType, lookup->SubTable + j);
+                                    lookup->LookupType,
+                                    lookup->SubTable.gpos + j);
 
       printf (")");
     }
   printf (")");
 }
 
+static void
+dump_rule_list (int indent, OTF_Rule *rule, int count)
+{
+  int i;
+
+  IPRINT ("(RuleCount %d)", count);
+  for (i = 0; i < count; i++)
+    {
+      IPRINT ("(Rule (%d)", i);
+      indent++;
+      IPRINT ("(GlyphCount %d)", rule[i].GlyphCount);
+      IPRINT ("(LookupCount %d)", rule[i].LookupCount);
+      dump_glyph_ids (indent, "Input", rule[i].Input, rule[i].GlyphCount - 1);
+      dump_lookup_record_list (indent, rule[i].LookupRecord,
+                              rule[i].LookupCount);
+      printf (")");
+      indent--;
+    }
+}
+
+static void
+dump_rule_set_list (int indent, OTF_RuleSet *set, int count)
+{
+  int i;
+
+  IPRINT ("(RuleSetCount %d)", count);
+  for (i = 0; i < count; i++)
+    {
+      IPRINT ("(RuleSet (%d)", i);
+      dump_rule_list (indent + 1, set[i].Rule, set[i].RuleCount);
+      printf (")");
+    }
+}
+
+static void
+dump_class_rule_list (int indent, OTF_ClassRule *rule, int count)
+{
+  int i, j;
+
+  IPRINT ("(ClassRuleCnt %d)", count);
+  for (i = 0; i < count; i++)
+    {
+      IPRINT ("(ClassRule (%d)", i);
+      indent++;
+      IPRINT ("(GlyphCount %d)", rule[i].GlyphCount);
+      IPRINT ("(LookupCount %d)", rule[i].LookupCount);
+      IPRINT ("(Class");
+      for (j = 0; j < rule[i].GlyphCount - 1; j++)
+       printf (" %d", rule[i].Class[j]);
+      printf (")");
+      dump_lookup_record_list (indent, rule[i].LookupRecord,
+                              rule[i].LookupCount);
+      printf (")");
+      indent--;
+    }
+}
+
+static void
+dump_class_set_list (int indent, OTF_ClassSet *set, int count)
+{
+  int i;
+
+  IPRINT ("(ClassSetCount %d)", count);
+  for (i = 0; i < count; i++)
+    if (set[i].offset)
+      {
+       IPRINT ("(ClassSet (%d)", i);
+       dump_class_rule_list (indent + 1, set[i].ClassRule,
+                             set[i].ClassRuleCnt);
+       printf (")");
+      }
+}
+
+static void
+dump_chain_rule_list (int indent, OTF_ChainRule *rule, int count)
+{
+  int i;
+
+  IPRINT ("(ChainRuleCount %d)", count);
+  for (i = 0; i < count; i++)
+    {
+      IPRINT ("(ChainRule (%d)", i);
+      dump_glyph_ids (indent + 1, "Backtrack",
+                     rule[i].Backtrack, rule[i].BacktrackGlyphCount);
+      dump_glyph_ids (indent + 1, "Input",
+                     rule[i].Input, rule[i].InputGlyphCount - 1);
+      dump_glyph_ids (indent + 1, "LookAhead",
+                     rule[i].LookAhead, rule[i].LookaheadGlyphCount);
+      dump_lookup_record_list (indent + 1, rule[i].LookupRecord,
+                              rule[i].LookupCount);
+      printf (")");
+    }
+}
+
+static void
+dump_chain_rule_set_list (int indent, OTF_ChainRuleSet *set, int count)
+{
+  int i;
+
+  IPRINT ("(ChainRuleSetCount %d)", count);
+  for (i = 0; i < count; i++)
+    {
+      IPRINT ("(ChainRuleSet (%d)", i);
+      dump_chain_rule_list (indent + 1,
+                           set[i].ChainRule, set[i].ChainRuleCount);
+      printf (")");
+    }
+}
+
+static void
+dump_chain_class_rule_list (int indent, OTF_ChainClassRule *rule, int count)
+{
+  int i;
+
+  IPRINT ("(ChainClassRuleCount %d)", count);
+  for (i = 0; i < count; i++)
+    {
+      IPRINT ("(ChainClassRule (%d)", i);
+      dump_glyph_ids (indent + 1, "Backtrack",
+                     rule[i].Backtrack, rule[i].BacktrackGlyphCount);
+      dump_glyph_ids (indent + 1, "Input",
+                     rule[i].Input, rule[i].InputGlyphCount - 1);
+      dump_glyph_ids (indent + 1, "LookAhead",
+                     rule[i].LookAhead, rule[i].LookaheadGlyphCount);
+      dump_lookup_record_list (indent + 1, rule[i].LookupRecord,
+                              rule[i].LookupCount);
+      printf (")");
+    }
+}
+
+static void
+dump_chain_class_set_list (int indent, OTF_ChainClassSet *set, int count)
+{
+  int i;
+
+  IPRINT ("(ChainClassSetCount %d)", count);
+  for (i = 0; i < count; i++)
+    {
+      IPRINT ("(ChainClassSet (%d)", i);
+      dump_chain_class_rule_list (indent + 1,
+                                 set[i].ChainClassRule,
+                                 set[i].ChainClassRuleCnt);
+      printf (")");
+    }
+}
+
+
+
 
 \f
 /* GSUB */
 
 static void
 dump_lookup_subtable_gsub (int indent, int index, unsigned type,
-                          OTF_LookupSubTable *subtable)
+                          OTF_LookupSubTableGSUB *subtable)
 {
   IPRINT ("(SubTable (%d) (Format %d)", index, subtable->Format);
   indent++;
@@ -490,91 +737,145 @@ dump_lookup_subtable_gsub (int indent, int index, unsigned type,
     case 1:
       if (subtable->Format == 1)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          IPRINT ("(DeltaGlyhpID #x%04X)",
-                 subtable->sub.gsub.single1.DeltaGlyphID);
+                 subtable->u.single1.DeltaGlyphID);
        }
       else if (subtable->Format == 2)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
-         IPRINT ("(GlyphCount %d)",
-                 subtable->sub.gsub.single2.GlyphCount);
-         IPRINT ("(Substitute");
-         dump_glyph_ids (subtable->sub.gsub.single2.Substitute,
-                         subtable->sub.gsub.single2.GlyphCount);
-         printf (")");
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
+         dump_glyph_ids (indent, "Substitute", subtable->u.single2.Substitute,
+                         subtable->u.single2.GlyphCount);
        }
+      else
+       printf (" invalid");
       break;
 
     case 2:
       if (subtable->Format == 1)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          dump_sequence_list (indent,
-                             subtable->sub.gsub.multiple1.Sequence,
-                             subtable->sub.gsub.multiple1.SequenceCount);
+                             subtable->u.multiple1.Sequence,
+                             subtable->u.multiple1.SequenceCount);
        }
+      else
+       printf (" invalid");
       break;
       
+    case 3:
+      if (subtable->Format == 1)
+       {
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
+         dump_alternate_set_list (indent, subtable->u.alternate1.AlternateSet,
+                                  subtable->u.alternate1.AlternateSetCount);
+       }
+      else
+       printf (" invalid");
+      break;
+
     case 4:
       if (subtable->Format == 1)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
-         dump_ligature_set_list (indent,
-                                 subtable->sub.gsub.ligature1.LigatureSet,
-                                 subtable->sub.gsub.ligature1.LigSetCount);
+         int *char_list = dump_coverage (indent, NULL, &subtable->Coverage);
+         dump_ligature_set_list (indent, char_list,
+                                 subtable->u.ligature1.LigatureSet,
+                                 subtable->u.ligature1.LigSetCount);
+         free (char_list);
+       }
+      else
+       printf (" invalid");
+      break;
+
+    case 5:
+      if (subtable->Format == 1)
+       {
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
+         dump_rule_set_list (indent, subtable->u.context1.RuleSet,
+                             subtable->u.context1.RuleSetCount); 
+       }
+      else if (subtable->Format == 2)
+       {
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
+         dump_class_def (indent, NULL, &subtable->u.context2.ClassDef);
+         dump_class_set_list (indent, subtable->u.context2.ClassSet,
+                              subtable->u.context2.ClassSetCnt);
+       }
+      else if (subtable->Format == 3)
+       {
+         dump_coverage_list (indent, "Coverage",
+                             subtable->u.context3.Coverage,
+                             subtable->u.context3.GlyphCount);
+         dump_lookup_record_list (indent,
+                                  subtable->u.context3.LookupRecord,
+                                  subtable->u.context3.LookupCount);
        }
+      else
+       printf (" invalid");
       break;
 
     case 6:
       if (subtable->Format == 1)
        {
-#if 0
-         read_coverage (fp, offset,
-                        &subtable->sub.gsub.chain_context1.Coverage);
-         subtable->sub.gsub.chain_context1.ChainSubRuleSetCount
-           = (read_chain_subrule_set
-              (fp, offset,
-               &subtable->sub.gsub.chain_context1.ChainSubRuleSet));
-#endif
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
+         dump_chain_rule_set_list
+           (indent,
+            subtable->u.chain_context1.ChainRuleSet,
+            subtable->u.chain_context1.ChainRuleSetCount);
        }
       else if (subtable->Format == 2)
        {
-#if 0
-         read_coverage (fp, offset,
-                        &subtable->sub.gsub.chain_context2.Coverage);
-         read_class_def (fp, offset,
-                         &subtable->sub.gsub.chain_context2.Backtrack);
-         read_class_def (fp, offset,
-                         &subtable->sub.gsub.chain_context2.Input);
-         read_class_def (fp, offset,
-                         &subtable->sub.gsub.chain_context2.LookAhead);
-         subtable->sub.gsub.chain_context2.ChainSubClassSetCnt
-           = (read_chain_subclass_set
-              (fp, offset,
-               &subtable->sub.gsub.chain_context2.ChainSubClassSet));
-#endif
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
+         dump_class_def (indent, "BacktrackClassDef",
+                         &subtable->u.chain_context2.BacktrackClassDef);
+         dump_class_def (indent, "InputClassDef",
+                         &subtable->u.chain_context2.InputClassDef);
+         dump_class_def (indent, "LookaheadClassDef",
+                         &subtable->u.chain_context2.LookaheadClassDef);
+         dump_chain_class_set_list
+           (indent,
+            subtable->u.chain_context2.ChainClassSet,
+            subtable->u.chain_context2.ChainClassSetCnt);
        }
       else if (subtable->Format == 3)
        {
          dump_coverage_list
            (indent, "BackTrackGlyphCount",
-            subtable->sub.gsub.chain_context3.Backtrack,
-            subtable->sub.gsub.chain_context3.BacktrackGlyphCount);
+            subtable->u.chain_context3.Backtrack,
+            subtable->u.chain_context3.BacktrackGlyphCount);
          dump_coverage_list
            (indent, "InputGlyphCount",
-            subtable->sub.gsub.chain_context3.Input,
-            subtable->sub.gsub.chain_context3.InputGlyphCount);
+            subtable->u.chain_context3.Input,
+            subtable->u.chain_context3.InputGlyphCount);
          dump_coverage_list
-           (indent, "LookaheaGlyphCount",
-            subtable->sub.gsub.chain_context3.LookAhead,
-            subtable->sub.gsub.chain_context3.LookaheadGlyphCount);
-         dump_subst_lookup_record_list
+           (indent, "LookaheadGlyphCount",
+            subtable->u.chain_context3.LookAhead,
+            subtable->u.chain_context3.LookaheadGlyphCount);
+         dump_lookup_record_list
            (indent,
-            subtable->sub.gsub.chain_context3.SubstLookupRecord,
-            subtable->sub.gsub.chain_context3.SubstCount);
+            subtable->u.chain_context3.LookupRecord,
+            subtable->u.chain_context3.LookupCount);
        }
+      else
+       printf (" invalid");
+      break;
+
+    case 7:
+      IPRINT ("(ExtensionLookupType %d)",
+             subtable->u.extension1.ExtensionLookupType);
+      IPRINT ("(ExtensionOffset %d)",
+             subtable->u.extension1.ExtensionOffset);
+      dump_lookup_subtable_gsub (indent, index, 
+                                subtable->u.extension1.ExtensionLookupType,
+                                subtable->u.extension1.ExtensionSubtable);
+      break;
+
+    case 8:
+      printf (" not-yet-supported");
       break;
+
+    default:
+      printf (" invalid");
     }
   printf (")");
 }
@@ -602,125 +903,208 @@ dump_gsub_table (int indent, OTF_GSUB *gsub)
 
 static void
 dump_lookup_subtable_gpos (int indent, int index, unsigned type,
-                          OTF_LookupSubTable *subtable)
+                          OTF_LookupSubTableGPOS *subtable)
 {
   IPRINT ("(SubTable (%d) (Format %d)", index, subtable->Format);
   indent++;
   switch (type)
     {
     case 1:
-#if 0
       if (subtable->Format == 1)
        {
-         dump_coverage (indent, NULL, &subtable->sub.gpos.single1.Coverage);
-         IPRINT ("(DeltaGlyhpID #x%04X)",
-                 subtable->sub.gsub.single1.DeltaGlyphID);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
+         IPRINT ("(ValueFormat #x%04X)",
+                 subtable->u.single1.ValueFormat);
+         dump_value_record (indent, "Value", &subtable->u.single1.Value);
        }
       else if (subtable->Format == 2)
        {
-         dump_coverage (indent, NULL, &subtable->sub.gsub.single2.Coverage);
-         IPRINT ("(GlyphCount %d)",
-                 subtable->sub.gsub.single2.GlyphCount);
-         IPRINT ("(Substitute");
-         dump_glyph_ids (subtable->sub.gsub.single2.Substitute,
-                         subtable->sub.gsub.single2.GlyphCount);
-         printf (")");
+         int i;
+
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
+         IPRINT ("(ValueFormat #x%04X)",
+                 subtable->u.single2.ValueFormat);
+         IPRINT ("(ValueCount %d)",
+                 subtable->u.single2.ValueCount);
+         for (i = 0; i < subtable->u.single2.ValueCount; i++)
+           dump_value_record (indent, "Value", &subtable->u.single2.Value[i]);
        }
-#endif
+      else
+       printf (" invalid");
       break;
 
     case 2:
       if (subtable->Format == 1)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
+         IPRINT ("(ValueFormat1 #x%04X)",
+                 subtable->u.pair1.ValueFormat1);
+         IPRINT ("(ValueFormat2 #x%04X)",
+                 subtable->u.pair1.ValueFormat2);
+         dump_pair_set_list (indent, subtable->u.pair1.PairSetCount,
+                             subtable->u.pair1.PairSet);
        }
       else if (subtable->Format == 2)
        {
-         dump_coverage (indent, NULL, &subtable->Coverage);
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
          IPRINT ("(ValueFormat1 #x%04X)",
-                 subtable->sub.gpos.pair2.ValueFormat1);
+                 subtable->u.pair2.ValueFormat1);
          IPRINT ("(ValueFormat2 #x%04X)",
-                 subtable->sub.gpos.pair2.ValueFormat2);
+                 subtable->u.pair2.ValueFormat2);
          dump_class_def (indent, "ClassDef1",
-                         &subtable->sub.gpos.pair2.ClassDef1);
+                         &subtable->u.pair2.ClassDef1);
          dump_class_def (indent, "ClassDef2",
-                         &subtable->sub.gpos.pair2.ClassDef2);
+                         &subtable->u.pair2.ClassDef2);
          IPRINT ("(Class1Count %d)",
-                 subtable->sub.gpos.pair2.Class1Count);
+                 subtable->u.pair2.Class1Count);
          IPRINT ("(Class2Count %d)",
-                 subtable->sub.gpos.pair2.Class2Count);
+                 subtable->u.pair2.Class2Count);
          dump_class1_record_list (indent,
-                                  subtable->sub.gpos.pair2.Class1Count,
-                                  subtable->sub.gpos.pair2.Class2Count,
-                                  subtable->sub.gpos.pair2.Class1Record);
+                                  subtable->u.pair2.Class1Count,
+                                  subtable->u.pair2.Class2Count,
+                                  subtable->u.pair2.Class1Record);
        }
+      else
+       printf (" invalid");
       break;
       
+    case 3:
+      if (subtable->Format == 1)
+       {
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
+         dump_entry_exit_list (indent, subtable->u.cursive1.EntryExitCount,
+                               subtable->u.cursive1.EntryExitRecord);
+       }
+      else
+       printf (" invalid");
+      break;
+
     case 4:
       if (subtable->Format == 1)
        {
-         dump_coverage (indent, "Mark", &subtable->Coverage);
-         dump_coverage (indent, "Base",
-                        &subtable->sub.gpos.mark_base1.BaseCoverage);
+         free (dump_coverage (indent, "Mark", &subtable->Coverage));
+         free (dump_coverage (indent, "Base",
+                              &subtable->u.mark_base1.BaseCoverage));
          IPRINT ("(ClassCount %d)",
-                 subtable->sub.gpos.mark_base1.ClassCount);
-         dump_mark_array (indent, &subtable->sub.gpos.mark_base1.MarkArray);
-         dump_base_array (indent, subtable->sub.gpos.mark_base1.ClassCount,
-                          &subtable->sub.gpos.mark_base1.BaseArray);
+                 subtable->u.mark_base1.ClassCount);
+         dump_mark_array (indent, &subtable->u.mark_base1.MarkArray);
+         dump_anchor_array (indent, subtable->u.mark_base1.ClassCount,
+                          &subtable->u.mark_base1.BaseArray);
+       }
+      break;
+
+    case 5:
+      if (subtable->Format == 1)
+       {
+         printf (" not-yet-supported");
        }
+      else
+       printf (" invalid");
       break;
 
     case 6:
       if (subtable->Format == 1)
        {
-#if 0
-         read_coverage (fp, offset,
-                        &subtable->sub.gsub.chain_context1.Coverage);
-         subtable->sub.gsub.chain_context1.ChainSubRuleSetCount
-           = (read_chain_subrule_set
-              (fp, offset,
-               &subtable->sub.gsub.chain_context1.ChainSubRuleSet));
-#endif
+         free (dump_coverage (indent, "Mark1", &subtable->Coverage));
+         free (dump_coverage (indent, "Mark2",
+                              &subtable->u.mark_mark1.Mark2Coverage));
+         IPRINT ("(ClassCount %d)",
+                 subtable->u.mark_mark1.ClassCount);
+         dump_mark_array (indent, &subtable->u.mark_mark1.Mark1Array);
+         dump_anchor_array (indent, subtable->u.mark_mark1.ClassCount,
+                          &subtable->u.mark_mark1.Mark2Array);
+       }
+      else
+       printf (" invalid");
+      break;
+
+    case 7:
+      if (subtable->Format == 1)
+       {
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
+         dump_rule_set_list (indent, subtable->u.context1.RuleSet,
+                             subtable->u.context1.RuleSetCount); 
        }
       else if (subtable->Format == 2)
        {
-#if 0
-         read_coverage (fp, offset,
-                        &subtable->sub.gsub.chain_context2.Coverage);
-         read_class_def (fp, offset,
-                         &subtable->sub.gsub.chain_context2.Backtrack);
-         read_class_def (fp, offset,
-                         &subtable->sub.gsub.chain_context2.Input);
-         read_class_def (fp, offset,
-                         &subtable->sub.gsub.chain_context2.LookAhead);
-         subtable->sub.gsub.chain_context2.ChainSubClassSetCnt
-           = (read_chain_subclass_set
-              (fp, offset,
-               &subtable->sub.gsub.chain_context2.ChainSubClassSet));
-#endif
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
+         dump_class_def (indent, NULL, &subtable->u.context2.ClassDef);
+         dump_class_set_list (indent, subtable->u.context2.ClassSet,
+                              subtable->u.context2.ClassSetCnt);
+       }
+      else if (subtable->Format == 3)
+       {
+         dump_coverage_list (indent, "Coverage",
+                             subtable->u.context3.Coverage,
+                             subtable->u.context3.GlyphCount);
+         dump_lookup_record_list (indent,
+                                  subtable->u.context3.LookupRecord,
+                                  subtable->u.context3.LookupCount);
+       }
+      else
+       printf (" invalid");
+      break;
+
+    case 8:
+      if (subtable->Format == 1)
+       {
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
+         dump_chain_rule_set_list
+           (indent,
+            subtable->u.chain_context1.ChainRuleSet,
+            subtable->u.chain_context1.ChainRuleSetCount);
+       }
+      else if (subtable->Format == 2)
+       {
+         free (dump_coverage (indent, NULL, &subtable->Coverage));
+         dump_class_def (indent, "BacktrackClassDef",
+                         &subtable->u.chain_context2.BacktrackClassDef);
+         dump_class_def (indent, "InputClassDef",
+                         &subtable->u.chain_context2.InputClassDef);
+         dump_class_def (indent, "LookaheadClassDef",
+                         &subtable->u.chain_context2.LookaheadClassDef);
+         dump_chain_class_set_list
+           (indent,
+            subtable->u.chain_context2.ChainClassSet,
+            subtable->u.chain_context2.ChainClassSetCnt);
        }
       else if (subtable->Format == 3)
        {
-#if 0
          dump_coverage_list
            (indent, "BackTrackGlyphCount",
-            subtable->sub.gsub.chain_context3.Backtrack,
-            subtable->sub.gsub.chain_context3.BacktrackGlyphCount);
+            subtable->u.chain_context3.Backtrack,
+            subtable->u.chain_context3.BacktrackGlyphCount);
          dump_coverage_list
            (indent, "InputGlyphCount",
-            subtable->sub.gsub.chain_context3.Input,
-            subtable->sub.gsub.chain_context3.InputGlyphCount);
+            subtable->u.chain_context3.Input,
+            subtable->u.chain_context3.InputGlyphCount);
          dump_coverage_list
            (indent, "LookaheaGlyphCount",
-            subtable->sub.gsub.chain_context3.LookAhead,
-            subtable->sub.gsub.chain_context3.LookaheadGlyphCount);
-         dump_subst_lookup_record_list
+            subtable->u.chain_context3.LookAhead,
+            subtable->u.chain_context3.LookaheadGlyphCount);
+         dump_lookup_record_list
            (indent,
-            subtable->sub.gsub.chain_context3.SubstLookupRecord,
-            subtable->sub.gsub.chain_context3.SubstCount);
-#endif
+            subtable->u.chain_context3.LookupRecord,
+            subtable->u.chain_context3.LookupCount);
        }
+      else
+       printf (" invalid");
       break;
+
+    case 9:
+      if (subtable->Format == 1)
+       {
+         IPRINT ("(ExtensionLookupType %d)",
+                 subtable->u.extension1.ExtensionLookupType);
+         IPRINT ("(ExtensionOffset %d)",
+                 subtable->u.extension1.ExtensionOffset);
+         dump_lookup_subtable_gpos
+           (indent, index, 
+            subtable->u.extension1.ExtensionLookupType,
+            subtable->u.extension1.ExtensionSubtable);
+       }
+      else
+       printf (" invalid");
     }
   printf (")");
 }
@@ -763,7 +1147,7 @@ dump_jstf_table (OTF_JSTF *jstf)
 static void
 dump_gdef_header (int indent, OTF_GDEFHeader *header)
 {
-  IPRINT ("(Header\n");
+  IPRINT ("(Header");
   indent++;
   IPRINT ("(Version %d.%d)",
          header->Version.high, header->Version.low);
@@ -786,7 +1170,7 @@ dump_lig_caret_list (int indent, OTF_LigCaretList *list)
 
   IPRINT ("(LigCaretList");
   indent++;
-  dump_coverage (indent, NULL, &list->Coverage);
+  free (dump_coverage (indent, NULL, &list->Coverage));
   IPRINT ("(LigGlyphCount %d)", list->LigGlyphCount);
   for (i = 0; i < list->LigGlyphCount; i++)
     {
@@ -922,6 +1306,25 @@ dump_cmap_table (int indent, OTF_cmap *cmap)
            printf (")");
          }
          break;
+
+       case 6:
+         {
+           OTF_EncodingSubtable6 *sub6
+             = cmap->EncodingRecord[i].subtable.f.f6;
+           int j;
+
+           IPRINT ("(firstCode %d) (entryCount %d)",
+                   sub6->firstCode, sub6->entryCount);
+           IPRINT ("(glyphIdArray");
+           for (j = 0; j < sub6->entryCount; j++)
+             {
+               if ((j % 16) == 0)
+                 IPRINT (" ");
+               printf (" %3d", sub6->glyphIdArray[j]);
+             }
+           printf (")");
+         }
+         break;
        }
 
       indent -= 2;
@@ -1000,30 +1403,29 @@ main (int argc, char **argv)
 {
   OTF *otf;
 
-  EF_ALIGNMENT = 1;
-  EF_PROTECT_BELOW = 1;
-  EF_PROTECT_FREE = 1;
-
-  if (argc != 2)
+  if (argc != 2 || !strcmp (argv[1], "-h") || !strcmp (argv[1], "--help"))
     {
-      fprintf (stderr, "Usage, dtfdump OTF-FILE");
-      exit (1);
+      fprintf (stderr, "Usage: %s OTF-FILE\n", basename (argv[0]));
+      exit (argc != 2);
     }
   
-  otf = otf_open (argv[1]);
+  otf = OTF_open (argv[1]);
   if (! otf)
-    otf_perror ("otfdump: ", 1);
-  otf_get_table (otf, "head");
-  otf_get_table (otf, "name");
-  otf_get_table (otf, "cmap");
-  otf_get_table (otf, "GDEF");
-  otf_get_table (otf, "GSUB");
-  otf_get_table (otf, "GPOS");
+    {
+      OTF_perror ("otfdump");
+      exit (1);
+    }
+  OTF_get_table (otf, "head");
+  OTF_get_table (otf, "name");
+  OTF_get_table (otf, "cmap");
+  OTF_get_table (otf, "GDEF");
+  OTF_get_table (otf, "GSUB");
+  OTF_get_table (otf, "GPOS");
 #if 0
-  otf_get_table (otf, "BASE");
-  otf_get_table (otf, "JSTF");
+  OTF_get_table (otf, "BASE");
+  OTF_get_table (otf, "JSTF");
 #endif
   otf_dump (otf);
-  otf_close (otf);
+  OTF_close (otf);
   exit (0);
 }