[util] Add hb-shape utility

Like hb-view, but prints out buffer contents.

The output format is kinda cryptic.  Suggestions welcome.
diff --git a/util/options.cc b/util/options.cc
index 96d131f..21ab973 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -31,6 +31,23 @@
 #endif
 
 
+void
+fail (hb_bool_t suggest_help, const char *format, ...)
+{
+  const char *msg;
+
+  va_list vap;
+  va_start (vap, format);
+  msg = g_strdup_vprintf (format, vap);
+  const char *prgname = g_get_prgname ();
+  g_printerr ("%s: %s\n", prgname, msg);
+  if (suggest_help)
+    g_printerr ("Try `%s --help' for more information.\n", prgname);
+
+  exit (1);
+}
+
+
 bool debug = FALSE;
 
 static gchar *
@@ -118,6 +135,8 @@
 void
 option_parser_t::parse (int *argc, char ***argv)
 {
+  setlocale (LC_ALL, "");
+
   GError *parse_error = NULL;
   if (!g_option_context_parse (context, argc, argv, &parse_error))
   {
@@ -590,3 +609,63 @@
 
   return fp;
 }
+
+
+void
+format_options_t::add_options (option_parser_t *parser)
+{
+  GOptionEntry entries[] =
+  {
+    {"no-glyph-names",	0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE,	&this->show_glyph_names,	"Use glyph indices instead of names",	NULL},
+    {"no-positions",	0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE,	&this->show_positions,		"Do not show glyph positions",		NULL},
+    {"no-clusters",	0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE,	&this->show_clusters,		"Do not show cluster mapping",		NULL},
+    {NULL}
+  };
+  parser->add_group (entries,
+		     "format",
+		     "Format options:",
+		     "Options controlling the formatting of buffer contents",
+		     this);
+}
+
+void
+format_options_t::serialize (hb_buffer_t *buffer,
+			     hb_font_t   *font,
+			     GString     *gs)
+{
+  FT_Face ft_face = show_glyph_names ? hb_ft_font_get_face (font) : NULL;
+
+  unsigned int num_glyphs = hb_buffer_get_length (buffer);
+  hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL);
+  hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL);
+
+  g_string_append_c (gs, '<');
+  for (unsigned int i = 0; i < (int) num_glyphs; i++)
+  {
+    if (i)
+      g_string_append_c (gs, '|');
+    char glyph_name[30];
+    if (show_glyph_names && !FT_Get_Glyph_Name (ft_face, info->codepoint, glyph_name, sizeof (glyph_name)))
+      g_string_append_printf (gs, "%s", glyph_name);
+    else
+      g_string_append_printf (gs, "gid%d", info->codepoint);
+
+    if (show_clusters)
+      g_string_append_printf (gs, "=%d", info->cluster);
+
+    if (show_positions && (pos->x_offset || pos->y_offset)) {
+      g_string_append_c (gs, '@');
+      if (pos->x_offset) g_string_append_printf (gs, "%d", pos->x_offset);
+      if (pos->y_offset) g_string_append_printf (gs, ",%d", pos->y_offset);
+    }
+    if (show_positions && (pos->x_advance || pos->y_advance)) {
+      g_string_append_c (gs, '+');
+      if (pos->x_advance) g_string_append_printf (gs, "%d", pos->x_advance);
+      if (pos->y_advance) g_string_append_printf (gs, ",%d", pos->y_advance);
+    }
+
+    info++;
+    pos++;
+  }
+  g_string_append_c (gs, '>');
+}