[repacker] expose hb_subset_repack() API, hb_object_t and hb_link_t structs
diff --git a/src/Makefile.sources b/src/Makefile.sources
index ce65014..40fbd99 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -275,6 +275,7 @@
 	hb-subset-input.hh \
 	hb-subset-plan.cc \
 	hb-subset-plan.hh \
+	hb-subset-repacker.cc \
 	hb-subset.cc \
 	hb-subset.hh \
 	hb-repacker.hh \
@@ -282,6 +283,7 @@
 
 HB_SUBSET_headers = \
 	hb-subset.h \
+	hb-subset-repacker.h \
 	$(NULL)
 
 HB_GOBJECT_DIST_sources = hb-gobject-structs.cc
diff --git a/src/gen-def.py b/src/gen-def.py
index 7b609a9..205ed7e 100755
--- a/src/gen-def.py
+++ b/src/gen-def.py
@@ -19,7 +19,7 @@
 if '--experimental-api' not in sys.argv:
 	# Move these to harfbuzz-sections.txt when got stable
 	experimental_symbols = \
-"""""".splitlines ()
+"""hb_subset_repack_or_fail""".splitlines ()
 	symbols = [x for x in symbols if x not in experimental_symbols]
 symbols = "\n".join (symbols)
 
diff --git a/src/hb-repacker.hh b/src/hb-repacker.hh
index b1726d8..2a9e75c 100644
--- a/src/hb-repacker.hh
+++ b/src/hb-repacker.hh
@@ -37,7 +37,6 @@
  * For a detailed writeup on the overflow resolution algorithm see:
  * docs/repacker.md
  */
-
 struct graph_t
 {
   struct vertex_t
@@ -140,7 +139,8 @@
    * the 'packed' object stack used internally in the
    * serializer
    */
-  graph_t (const hb_vector_t<hb_serialize_context_t::object_t *>& objects)
+  template<typename T>
+  graph_t (const T& objects)
       : parents_invalid (true),
         distance_invalid (true),
         positions_invalid (true),
@@ -1098,8 +1098,9 @@
   hb_vector_t<unsigned> num_roots_for_space_;
 };
 
-static bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& overflows,
-                                      graph_t& sorted_graph)
+static inline
+bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& overflows,
+                               graph_t& sorted_graph)
 {
   unsigned space = 0;
   hb_set_t roots_to_isolate;
@@ -1147,9 +1148,10 @@
   return true;
 }
 
-static bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflows,
-                                hb_set_t& priority_bumped_parents,
-                                graph_t& sorted_graph)
+static inline
+bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflows,
+                         hb_set_t& priority_bumped_parents,
+                         graph_t& sorted_graph)
 {
   bool resolution_attempted = false;
 
@@ -1207,8 +1209,9 @@
  * For a detailed writeup describing how the algorithm operates see:
  * docs/repacker.md
  */
+template<typename T>
 inline hb_blob_t*
-hb_resolve_overflows (const hb_vector_t<hb_serialize_context_t::object_t *>& packed,
+hb_resolve_overflows (const T& packed,
                       hb_tag_t table_tag,
                       unsigned max_rounds = 20) {
   // Kahn sort is ~twice as fast as shortest distance sort and works for many fonts
diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh
index 6615f03..40895a4 100644
--- a/src/hb-serialize.hh
+++ b/src/hb-serialize.hh
@@ -36,6 +36,9 @@
 #include "hb-map.hh"
 #include "hb-pool.hh"
 
+#ifdef HB_EXPERIMENTAL_API
+#include "hb-subset-repacker.h"
+#endif
 
 /*
  * Serialize
@@ -70,6 +73,24 @@
       virtual_links.fini ();
     }
 
+    object_t () = default;
+    
+#ifdef HB_EXPERIMENTAL_API
+    object_t (const hb_object_t &o)
+    {
+      head = o.head;
+      tail = o.tail;
+      next = nullptr;
+      real_links.alloc (o.num_real_links);
+      for (unsigned i = 0 ; i < o.num_real_links; i++)
+        real_links.push (o.real_links[i]);
+
+      virtual_links.alloc (o.num_virtual_links);
+      for (unsigned i = 0; i < o.num_virtual_links; i++)
+        virtual_links.push (o.virtual_links[i]);
+    }
+#endif
+
     bool operator == (const object_t &o) const
     {
       // Virtual links aren't considered for equality since they don't affect the functionality
@@ -95,6 +116,20 @@
       unsigned position: 28;
       unsigned bias;
       objidx_t objidx;
+
+      link_t () = default;
+
+#ifdef HB_EXPERIMENTAL_API
+      link_t (const hb_link_t &o)
+      {
+        width = o.width;
+        is_signed = 0;
+        whence = 0;
+        position = o.position;
+        bias = 0;
+        objidx = o.objidx;
+      }
+#endif
     };
 
     char *head;
diff --git a/src/hb-subset-repacker.cc b/src/hb-subset-repacker.cc
new file mode 100644
index 0000000..2447d29
--- /dev/null
+++ b/src/hb-subset-repacker.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2022  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+#include "hb-repacker.hh"
+
+#ifdef HB_EXPERIMENTAL_API
+/**
+ * hb_subset_repack_or_fail:
+ * @hb_objects: raw array of struct hb_object_t, which provides
+ * object graph info
+ * @num_hb_objs: number of hb_object_t in the hb_objects array.
+ *
+ * Given the input object graph info, repack a table to eliminate
+ * offset overflows. A nullptr is returned if the repacking attempt fails.
+ *
+ * Since: EXPERIMENTAL
+ **/
+hb_blob_t* hb_subset_repack_or_fail (hb_object_t* hb_objects, unsigned num_hb_objs)
+{
+  hb_vector_t<const hb_object_t *> packed;
+  packed.alloc (num_hb_objs + 1);
+  packed.push (nullptr);
+  for (unsigned i = 0 ; i < num_hb_objs ; i++)
+    packed.push (&(hb_objects[i]));
+  return hb_resolve_overflows (packed, HB_OT_TAG_GSUB);
+}
+#endif
+
diff --git a/src/hb-subset-repacker.h b/src/hb-subset-repacker.h
new file mode 100644
index 0000000..f9a2383
--- /dev/null
+++ b/src/hb-subset-repacker.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2022  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+#ifndef HB_SUBSET_REPACKER_H
+#define HB_SUBSET_REPACKER_H
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+
+#ifdef HB_EXPERIMENTAL_API
+/**
+ * struct hb_link_t
+ * width:    offsetSize in bytes
+ * position: position of the offset field in bytes
+ * from beginning of subtable
+ * objidx:   index of subtable
+ **/
+struct hb_link_t
+{
+  unsigned width;
+  unsigned position;
+  unsigned objidx;
+};
+
+typedef struct hb_link_t hb_link_t;
+
+/**
+ * struct hb_object_t
+ * head:    start of object data
+ * tail:    end of object data
+ * num_real_links:    num of offset field in the object
+ * real_links:        pointer to array of offset info
+ * num_virtual_links: num of objects that must be packed
+ * after current object in the final serialized order
+ * virtual_links:     array of virtual link info
+ **/
+struct hb_object_t
+{
+  char *head;
+  char *tail;
+  unsigned num_real_links;
+  hb_link_t *real_links;
+  unsigned num_virtual_links;
+  hb_link_t *virtual_links;
+};
+
+typedef struct hb_object_t hb_object_t;
+
+HB_EXTERN hb_blob_t*
+hb_subset_repack_or_fail (hb_object_t* hb_objects,
+                          unsigned num_hb_objs);
+
+#endif
+
+HB_END_DECLS
+
+#endif /* HB_SUBSET_REPACKER_H */
diff --git a/src/meson.build b/src/meson.build
index c9d3f17..e6a5f22 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -276,11 +276,15 @@
   'hb-subset-input.hh',
   'hb-subset-plan.cc',
   'hb-subset-plan.hh',
+  'hb-subset-repacker.cc',
   'hb-subset.cc',
   'hb-subset.hh',
 )
 
-hb_subset_headers = files('hb-subset.h')
+hb_subset_headers = files(
+  'hb-subset.h',
+  'hb-subset-repacker.h'
+)
 
 hb_gobject_sources = files(
   'hb-gobject-structs.cc'
diff --git a/test/api/Makefile.am b/test/api/Makefile.am
index a2412f9..ffd4a0f 100644
--- a/test/api/Makefile.am
+++ b/test/api/Makefile.am
@@ -78,6 +78,7 @@
 	test-subset-gpos \
 	test-subset-colr \
 	test-subset-cbdt \
+	test-subset-repacker \
 	test-unicode \
 	test-var-coords \
 	test-version \
@@ -105,6 +106,7 @@
 test_subset_nameids_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_gpos_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 test_subset_colr_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
+test_subset_repacker_LDADD = $(LDADD) $(top_builddir)/src/libharfbuzz-subset.la
 
 test_unicode_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
diff --git a/test/api/fonts/repacker_expected.otf b/test/api/fonts/repacker_expected.otf
new file mode 100644
index 0000000..d8ed678
--- /dev/null
+++ b/test/api/fonts/repacker_expected.otf
Binary files differ
diff --git a/test/api/meson.build b/test/api/meson.build
index ab64338..f5cdce8 100644
--- a/test/api/meson.build
+++ b/test/api/meson.build
@@ -32,6 +32,7 @@
   'test-ot-tag.c',
   'test-ot-extents-cff.c',
   'test-ot-metrics-tt-var.c',
+  'test-subset-repacker.c',
   'test-set.c',
   'test-shape.c',
   'test-style.c',
diff --git a/test/api/test-subset-repacker.c b/test/api/test-subset-repacker.c
new file mode 100644
index 0000000..e92683d
--- /dev/null
+++ b/test/api/test-subset-repacker.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright © 2022  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+#include "hb-test.h"
+#include "hb-subset-test.h"
+
+#ifdef HB_EXPERIMENTAL_API
+#include "hb-subset-repacker.h"
+
+char test_gsub_data[106] = "\x0\x1\x0\x0\x0\xa\x0\x1e\x0\x2c\x0\x1\x6c\x61\x74\x6e\x0\x8\x0\x4\x0\x0\x0\x0\xff\xff\x0\x1\x0\x0\x0\x1\x74\x65\x73\x74\x0\x8\x0\x0\x0\x1\x0\x1\x0\x2\x0\x2a\x0\x6\x0\x5\x0\x0\x0\x1\x0\x8\x0\x1\x0\x8\x0\x1\x0\xe\x0\x1\x0\x1\x0\x1\x0\x1\x0\x4\x0\x2\x0\x1\x0\x2\x0\x1\x0\x0\x0\x1\x0\x0\x0\x1\x0\x8\x0\x1\x0\x6\x0\x1\x0\x1\x0\x1\x0\x2";
+
+static void
+test_hb_repack_with_cy_struct (void)
+{
+  hb_object_t *hb_objs = calloc (15, sizeof (hb_object_t));
+
+  hb_objs[0].head = &(test_gsub_data[100]);
+  hb_objs[0].tail = &(test_gsub_data[105]) + 1;
+  hb_objs[0].num_real_links = 0;
+  hb_objs[0].num_virtual_links = 0;
+  hb_objs[0].real_links = NULL;
+  hb_objs[0].virtual_links = NULL;
+
+  hb_objs[1].head = &(test_gsub_data[94]);
+  hb_objs[1].tail = &(test_gsub_data[100]);
+  hb_objs[1].num_real_links = 1;
+  hb_objs[1].num_virtual_links = 0;
+  hb_objs[1].real_links = malloc (sizeof (hb_link_t));
+  hb_objs[1].real_links[0].width = 2;
+  hb_objs[1].real_links[0].position = 2;
+  hb_objs[1].real_links[0].objidx = 1;
+  hb_objs[1].virtual_links = NULL;
+
+
+  hb_objs[2].head = &(test_gsub_data[86]);
+  hb_objs[2].tail = &(test_gsub_data[94]);
+  hb_objs[2].num_real_links = 1;
+  hb_objs[2].num_virtual_links = 0;
+  hb_objs[2].real_links = malloc (sizeof (hb_link_t));
+  hb_objs[2].real_links[0].width = 2;
+  hb_objs[2].real_links[0].position = 6;
+  hb_objs[2].real_links[0].objidx = 2;
+  hb_objs[2].virtual_links = NULL;
+
+  hb_objs[3].head = &(test_gsub_data[76]);
+  hb_objs[3].tail = &(test_gsub_data[86]);
+  hb_objs[3].num_real_links = 0;
+  hb_objs[3].num_virtual_links = 0;
+  hb_objs[3].real_links = NULL;
+  hb_objs[3].virtual_links = NULL;
+
+  hb_objs[4].head = &(test_gsub_data[72]);
+  hb_objs[4].tail = &(test_gsub_data[76]);
+  hb_objs[4].num_real_links = 1;
+  hb_objs[4].num_virtual_links = 0;
+  hb_objs[4].real_links = malloc (sizeof (hb_link_t));
+  hb_objs[4].real_links[0].width = 2;
+  hb_objs[4].real_links[0].position = 2;
+  hb_objs[4].real_links[0].objidx = 4;
+  hb_objs[4].virtual_links = NULL;
+
+  hb_objs[5].head = &(test_gsub_data[66]);
+  hb_objs[5].tail = &(test_gsub_data[72]);
+  hb_objs[5].num_real_links = 0;
+  hb_objs[5].num_virtual_links = 0;
+  hb_objs[5].real_links = NULL;
+  hb_objs[5].virtual_links = NULL;
+
+  hb_objs[6].head = &(test_gsub_data[58]);
+  hb_objs[6].tail = &(test_gsub_data[66]);
+  hb_objs[6].num_real_links = 2;
+  hb_objs[6].num_virtual_links = 0;
+  hb_objs[6].real_links = calloc (2, sizeof (hb_link_t));
+  hb_objs[6].real_links[0].width = 2;
+  hb_objs[6].real_links[0].position = 6;
+  hb_objs[6].real_links[0].objidx = 5;
+  hb_objs[6].real_links[1].width = 2;
+  hb_objs[6].real_links[1].position = 2;
+  hb_objs[6].real_links[1].objidx = 6;
+  hb_objs[6].virtual_links = NULL;
+
+  hb_objs[7].head = &(test_gsub_data[50]);
+  hb_objs[7].tail = &(test_gsub_data[58]);
+  hb_objs[7].num_real_links = 1;
+  hb_objs[7].num_virtual_links = 0;
+  hb_objs[7].real_links = malloc (sizeof (hb_link_t));
+  hb_objs[7].real_links[0].width = 2;
+  hb_objs[7].real_links[0].position = 6;
+  hb_objs[7].real_links[0].objidx = 7;
+  hb_objs[7].virtual_links = NULL;
+
+  hb_objs[8].head = &(test_gsub_data[44]);
+  hb_objs[8].tail = &(test_gsub_data[50]);
+  hb_objs[8].num_real_links = 2;
+  hb_objs[8].num_virtual_links = 0;
+  hb_objs[8].real_links = calloc (2, sizeof (hb_link_t));
+  hb_objs[8].real_links[0].width = 2;
+  hb_objs[8].real_links[0].position = 2;
+  hb_objs[8].real_links[0].objidx = 3;
+  hb_objs[8].real_links[1].width = 2;
+  hb_objs[8].real_links[1].position = 4;
+  hb_objs[8].real_links[1].objidx = 8;
+  hb_objs[8].virtual_links = NULL;
+
+  hb_objs[9].head = &(test_gsub_data[38]);
+  hb_objs[9].tail = &(test_gsub_data[44]);
+  hb_objs[9].num_real_links = 0;
+  hb_objs[9].num_virtual_links = 0;
+  hb_objs[9].real_links = NULL;
+  hb_objs[9].virtual_links = NULL;
+
+  hb_objs[10].head = &(test_gsub_data[30]);
+  hb_objs[10].tail = &(test_gsub_data[38]);
+  hb_objs[10].num_real_links = 1;
+  hb_objs[10].num_virtual_links = 0;
+  hb_objs[10].real_links = malloc (sizeof (hb_link_t));
+  hb_objs[10].real_links[0].width = 2;
+  hb_objs[10].real_links[0].position = 6;
+  hb_objs[10].real_links[0].objidx = 10;
+  hb_objs[10].virtual_links = NULL;
+
+  hb_objs[11].head = &(test_gsub_data[22]);
+  hb_objs[11].tail = &(test_gsub_data[30]);
+  hb_objs[11].num_real_links = 0;
+  hb_objs[11].num_virtual_links = 0;
+  hb_objs[11].real_links = NULL;
+  hb_objs[11].virtual_links = NULL;
+
+  hb_objs[12].head = &(test_gsub_data[18]);
+  hb_objs[12].tail = &(test_gsub_data[22]);
+  hb_objs[12].num_real_links = 1;
+  hb_objs[12].num_virtual_links = 0;
+  hb_objs[12].real_links = malloc (sizeof (hb_link_t));
+  hb_objs[12].real_links[0].width = 2;
+  hb_objs[12].real_links[0].position = 0;
+  hb_objs[12].real_links[0].objidx = 12;
+  hb_objs[12].virtual_links = NULL;
+
+  hb_objs[13].head = &(test_gsub_data[10]);
+  hb_objs[13].tail = &(test_gsub_data[18]);
+  hb_objs[13].num_real_links = 1;
+  hb_objs[13].num_virtual_links = 0;
+  hb_objs[13].real_links = malloc (sizeof (hb_link_t));
+  hb_objs[13].real_links[0].width = 2;
+  hb_objs[13].real_links[0].position = 6;
+  hb_objs[13].real_links[0].objidx = 13;
+  hb_objs[13].virtual_links = NULL;
+
+  hb_objs[14].head = &(test_gsub_data[0]);
+  hb_objs[14].tail = &(test_gsub_data[10]);
+  hb_objs[14].num_real_links = 3;
+  hb_objs[14].num_virtual_links = 0;
+  hb_objs[14].real_links = calloc (3, sizeof (hb_link_t));
+  hb_objs[14].real_links[0].width = 2;
+  hb_objs[14].real_links[0].position = 8;
+  hb_objs[14].real_links[0].objidx = 9;
+  hb_objs[14].real_links[1].width = 2;
+  hb_objs[14].real_links[1].position = 6;
+  hb_objs[14].real_links[1].objidx = 11;
+  hb_objs[14].real_links[2].width = 2;
+  hb_objs[14].real_links[2].position = 4;
+  hb_objs[14].real_links[2].objidx = 14;
+  hb_objs[14].virtual_links = NULL;
+
+  hb_blob_t *result = hb_subset_repack_or_fail (hb_objs, 15);
+  
+  hb_face_t *face_expected = hb_test_open_font_file ("fonts/repacker_expected.otf");
+  hb_blob_t *expected_blob = hb_face_reference_table (face_expected, HB_TAG ('G','S','U','B'));
+  fprintf(stderr, "expected %d bytes, actual %d bytes\n", hb_blob_get_length(expected_blob), hb_blob_get_length (result));
+  
+  if (hb_blob_get_length (expected_blob) != 0 ||
+      hb_blob_get_length (result) != 0)
+    hb_test_assert_blobs_equal (expected_blob, result);
+
+  hb_face_destroy (face_expected);
+  hb_blob_destroy (expected_blob);
+  hb_blob_destroy (result);
+
+  for (unsigned i = 0 ; i < 15; i++)
+  {
+    if (hb_objs[i].real_links != NULL)
+      free (hb_objs[i].real_links);
+  }
+
+  free (hb_objs);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  hb_test_init (&argc, &argv);
+
+  hb_test_add (test_hb_repack_with_cy_struct);
+
+  return hb_test_run();
+}
+#else
+int main (int argc HB_UNUSED, char **argv HB_UNUSED)
+{
+  return 0;
+}
+#endif