summaryrefslogtreecommitdiff
path: root/tools/generate.c
diff options
context:
space:
mode:
authorRob Taylor <rob.taylor@codethink.co.uk>2008-02-08 15:31:03 +0000
committerRobert James Taylor <robtaylor@src.gnome.org>2008-02-08 15:31:03 +0000
commitb935261f387dffa2c7006fe1be04820004810e87 (patch)
tree0c077cee05c725e1e56309374a1ceea8d8881b7d /tools/generate.c
parentc6c15af80d8a6d34e5c77d3111c638126edb3d45 (diff)
downloadgobject-introspection-b935261f387dffa2c7006fe1be04820004810e87.tar.gz
Added: Added: Renamed to tools/Makefile.am: Renamed to tools/compiler.c:
2008-02-08 Rob Taylor <rob.taylor@codethink.co.uk> * Makefile.am: * configure.ac: * gidl/Makefile.am: Added: * girepository/Makefile.am: Added: * src/Makefile.am: Renamed to tools/Makefile.am: * src/compiler.c: Renamed to tools/compiler.c: * src/g-idl-offsets.pl: Renamed to tools/g-idl-offsets.pl: * src/generate.c: Renamed to tools/generate.c: * src/gidlmodule.c: Renamed to tools/gidlmodule.c: * src/gidlmodule.h: Renamed to tools/gidlmodule.h: * src/gidlnode.c: Renamed to tools/gidlnode.c: * src/gidlnode.h: Renamed to tools/gidlnode.h: * src/gidlparser.c: Renamed to tools/gidlparser.c: * src/gidlparser.h: Renamed to tools/gidlparser.h: * src/gidlwriter.c: Renamed to tools/gidlwriter.c: * src/gidlwriter.h: Renamed to tools/gidlwriter.h: * src/ginfo.c: Renamed to girepository/ginfo.c: * src/ginvoke.c: Renamed to girepository/ginvoke.c: * src/girepository.c: Renamed to girepository/girepository.c: * src/girepository.h: Renamed to girepository/girepository.h: * src/gmetadata.c: Renamed to girepository/gmetadata.c: * src/gmetadata.h: Renamed to girepository/gmetadata.h: * src/scanner.c: Renamed to tools/scanner.c: * src/scanner.h: Renamed to tools/scanner.h: * src/scannerlexer.l: Renamed to tools/scannerlexer.l: * src/scannerparser.y: Renamed to tools/scannerparser.y: * tests/invoke/Makefile.am: Split src/ into girepository/ and tools/ * Makefile.am: * configure.ac: * girepository/Makefile.am: * tests/Makefile.am: * tests/invoke/Makefile.am: * tests/parser/Makefile.am: * tests/roundtrips.sh: * tools/Makefile.am: Make distcheck work. svn path=/trunk/; revision=104
Diffstat (limited to 'tools/generate.c')
-rw-r--r--tools/generate.c1223
1 files changed, 1223 insertions, 0 deletions
diff --git a/tools/generate.c b/tools/generate.c
new file mode 100644
index 00000000..8ae6fc35
--- /dev/null
+++ b/tools/generate.c
@@ -0,0 +1,1223 @@
+/* -*- Mode: C; c-file-style: "gnu"; -*- */
+/* GObject introspection: IDL generator
+ *
+ * Copyright (C) 2005 Matthias Clasen
+ *
+ * This library 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 of the License, or (at your option) any later version.
+ *
+ * This library 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; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <errno.h>
+#include <dlfcn.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gstdio.h>
+
+#include "girepository.h"
+#include "gmetadata.h"
+
+gboolean raw = FALSE;
+gchar **input = NULL;
+gchar *output = NULL;
+
+static void
+write_type_name (const gchar *namespace,
+ GIBaseInfo *info,
+ FILE *file)
+{
+ if (strcmp (namespace, g_base_info_get_namespace (info)) != 0)
+ g_fprintf (file, "%s.", g_base_info_get_namespace (info));
+
+ g_fprintf (file, "%s", g_base_info_get_name (info));
+}
+
+static void
+write_type_info (const gchar *namespace,
+ GITypeInfo *info,
+ FILE *file)
+{
+ gint tag;
+ gint i;
+ GITypeInfo *type;
+
+ const gchar* basic[] = {
+ "void",
+ "gboolean",
+ "gint8",
+ "guint8",
+ "gint16",
+ "guint16",
+ "gint32",
+ "guint32",
+ "gint64",
+ "guint64",
+ "gint",
+ "guint",
+ "glong",
+ "gulong",
+ "gssize",
+ "gsize",
+ "gfloat",
+ "gdouble",
+ "utf8",
+ "filename"
+ };
+
+ tag = g_type_info_get_tag (info);
+
+ if (tag < 18)
+ g_fprintf (file, "%s%s", basic[tag], g_type_info_is_pointer (info) ? "*" : "");
+ else if (tag < 20)
+ g_fprintf (file, "%s", basic[tag]);
+ else if (tag == 20)
+ {
+ gint length;
+
+ type = g_type_info_get_param_type (info, 0);
+ write_type_info (namespace, type, file);
+ g_fprintf (file, "[");
+
+ length = g_type_info_get_array_length (info);
+
+ if (length >= 0)
+ g_fprintf (file, "length=%d", length);
+
+ if (g_type_info_is_zero_terminated (info))
+ g_fprintf (file, "%szero-terminated=1", length >= 0 ? "," : "");
+
+ g_fprintf (file, "]");
+ g_base_info_unref ((GIBaseInfo *)type);
+ }
+ else if (tag == 21)
+ {
+ GIBaseInfo *iface = g_type_info_get_interface (info);
+ write_type_name (namespace, iface, file);
+ if (g_type_info_is_pointer (info))
+ g_fprintf (file, "*");
+ g_base_info_unref (iface);
+ }
+ else if (tag == 22)
+ {
+ type = g_type_info_get_param_type (info, 0);
+ g_fprintf (file, "GList");
+ if (type)
+ {
+ g_fprintf (file, "<");
+ write_type_info (namespace, type, file);
+ g_fprintf (file, ">");
+ g_base_info_unref ((GIBaseInfo *)type);
+ }
+ g_fprintf (file, "*");
+ }
+ else if (tag == 23)
+ {
+ type = g_type_info_get_param_type (info, 0);
+ g_fprintf (file, "GSList");
+ if (type)
+ {
+ g_fprintf (file, "<");
+ write_type_info (namespace, type, file);
+ g_fprintf (file, ">");
+ g_base_info_unref ((GIBaseInfo *)type);
+ }
+ g_fprintf (file, "*");
+ }
+ else if (tag == 24)
+ {
+ type = g_type_info_get_param_type (info, 0);
+ g_fprintf (file, "GHashTable");
+ if (type)
+ {
+ g_fprintf (file, "<");
+ write_type_info (namespace, type, file);
+ g_base_info_unref ((GIBaseInfo *)type);
+ type = g_type_info_get_param_type (info, 1);
+ g_fprintf (file, ",");
+ write_type_info (namespace, type, file);
+ g_fprintf (file, ">");
+ g_base_info_unref ((GIBaseInfo *)type);
+ }
+ g_fprintf (file, "*");
+ }
+ else if (tag == 25)
+ {
+ gint n;
+
+ g_fprintf (file, "GError");
+ n = g_type_info_get_n_error_domains (info);
+ if (n > 0)
+ {
+ g_fprintf (file, "<");
+ for (i = 0; i < n; i++)
+ {
+ GIErrorDomainInfo *ed = g_type_info_get_error_domain (info, i);
+ if (i > 0)
+ g_fprintf (file, ",");
+ write_type_name (namespace, (GIBaseInfo *)ed, file);
+ g_base_info_unref ((GIBaseInfo *)ed);
+ }
+ g_fprintf (file, ">");
+ }
+ g_fprintf (file, "*");
+ }
+}
+
+static void
+write_constant_value (const gchar *namespace,
+ GITypeInfo *info,
+ GArgument *argument,
+ FILE *file);
+
+static void
+write_field_info (const gchar *namespace,
+ GIFieldInfo *info,
+ GIConstantInfo *branch,
+ FILE *file)
+{
+ const gchar *name;
+ GIFieldInfoFlags flags;
+ gint size;
+ gint offset;
+ GITypeInfo *type;
+ GArgument value;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ flags = g_field_info_get_flags (info);
+ size = g_field_info_get_size (info);
+ offset = g_field_info_get_offset (info);
+
+ g_fprintf (file,
+ " <field name=\"%s\" readable=\"%s\" writable=\"%s\" ",
+ name,
+ flags & GI_FIELD_IS_READABLE ? "1" : "0",
+ flags & GI_FIELD_IS_WRITABLE ? "1" : "0");
+ if (size)
+ g_fprintf (file, "bits=\"%d\" ", size);
+ g_fprintf (file, "offset=\"%d\" ", offset);
+
+ g_fprintf (file, "type=\"");
+
+ type = g_field_info_get_type (info);
+ write_type_info (namespace, type, file);
+ g_base_info_unref ((GIBaseInfo *)type);
+
+ g_fprintf (file, "\"");
+
+ if (branch)
+ {
+ g_fprintf (file, " branch=\"");
+ type = g_constant_info_get_type (branch);
+ g_constant_info_get_value (branch, &value);
+ write_constant_value (namespace, type, &value, file);
+ g_fprintf (file, "\"");
+ }
+
+ g_fprintf (file," />\n");
+}
+
+static void
+write_callable_info (const gchar *namespace,
+ GICallableInfo *info,
+ FILE *file,
+ gint indent)
+{
+ GITypeInfo *type;
+ gint i;
+
+ g_fprintf (file, "%*s <return-type type=\"", indent, "");
+
+ type = g_callable_info_get_return_type (info);
+ write_type_info (namespace, type, file);
+
+ g_fprintf (file, "\"");
+
+ if (g_type_info_is_pointer (type))
+ {
+ switch (g_callable_info_get_caller_owns (info))
+ {
+ case GI_TRANSFER_NOTHING:
+ g_fprintf (file, " transfer=\"none\"");
+ break;
+ case GI_TRANSFER_CONTAINER:
+ g_fprintf (file, " transfer=\"shallow\"");
+ break;
+ case GI_TRANSFER_EVERYTHING:
+ g_fprintf (file, " transfer=\"full\"");
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ }
+ g_base_info_unref ((GIBaseInfo *)type);
+ if (g_callable_info_may_return_null (info))
+ g_fprintf (file, " null-ok=\"1\"");
+
+ g_fprintf (file, " />\n");
+
+ if (g_callable_info_get_n_args (info) > 0)
+ {
+ g_fprintf (file, "%*s <parameters>\n", indent, "");
+ for (i = 0; i < g_callable_info_get_n_args (info); i++)
+ {
+ GIArgInfo *arg = g_callable_info_get_arg (info, i);
+
+ g_fprintf (file, "%*s <parameter name=\"%s\" type=\"",
+ indent, "", g_base_info_get_name ((GIBaseInfo *) arg));
+
+ type = g_arg_info_get_type (arg);
+ write_type_info (namespace, type, file);
+ g_fprintf (file, "\"");
+
+ if (g_type_info_is_pointer (type))
+ {
+ switch (g_arg_info_get_ownership_transfer (arg))
+ {
+ case GI_TRANSFER_NOTHING:
+ g_fprintf (file, " transfer=\"none\"");
+ break;
+ case GI_TRANSFER_CONTAINER:
+ g_fprintf (file, " transfer=\"shallow\"");
+ break;
+ case GI_TRANSFER_EVERYTHING:
+ g_fprintf (file, " transfer=\"full\"");
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ }
+ g_base_info_unref ((GIBaseInfo *)type);
+
+ g_fprintf (file, " direction=\"");
+ switch (g_arg_info_get_direction (arg))
+ {
+ case GI_DIRECTION_IN:
+ g_fprintf (file, "in");
+ break;
+ case GI_DIRECTION_OUT:
+ g_fprintf (file, "out");
+ break;
+ case GI_DIRECTION_INOUT:
+ g_fprintf (file, "inout");
+ break;
+ }
+ g_fprintf (file, "\"");
+
+ if (g_arg_info_may_be_null (arg))
+ g_fprintf (file, " null-ok=\"1\"");
+
+ if (g_arg_info_is_dipper (arg))
+ g_fprintf (file, " dipper=\"1\"");
+
+ if (g_arg_info_is_return_value (arg))
+ g_fprintf (file, " retval=\"1\"");
+
+ if (g_arg_info_is_optional (arg))
+ g_fprintf (file, " optional=\"1\"");
+
+ g_fprintf (file, " />\n");
+
+ g_base_info_unref ((GIBaseInfo *)arg);
+ }
+
+ g_fprintf (file, "%*s </parameters>\n", indent, "");
+ }
+}
+
+static void
+write_function_info (const gchar *namespace,
+ GIFunctionInfo *info,
+ FILE *file,
+ gint indent)
+{
+ GIFunctionInfoFlags flags;
+ const gchar *tag;
+ const gchar *name;
+ const gchar *symbol;
+ gboolean deprecated;
+
+ flags = g_function_info_get_flags (info);
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ symbol = g_function_info_get_symbol (info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ if (flags & GI_FUNCTION_IS_CONSTRUCTOR)
+ tag = "constructor";
+ else if (flags & GI_FUNCTION_IS_METHOD)
+ tag = "method";
+ else
+ tag = "function";
+
+ g_fprintf (file, "%*s<%s name=\"%s\" symbol=\"%s\"",
+ indent, "", tag, name, symbol);
+
+ if (flags & GI_FUNCTION_IS_SETTER)
+ g_fprintf (file, " type=\"setter\"");
+ else if (flags & GI_FUNCTION_IS_GETTER)
+ g_fprintf (file, " type=\"getter\"");
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ g_fprintf (file, ">\n");
+ write_callable_info (namespace, (GICallableInfo*)info, file, indent);
+ g_fprintf (file, "%*s</%s>\n", indent, "", tag);
+}
+
+static void
+write_callback_info (const gchar *namespace,
+ GICallbackInfo *info,
+ FILE *file,
+ gint indent)
+{
+ const gchar *name;
+ gboolean deprecated;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ g_fprintf (file, "%*s<callback name=\"%s\"", indent, "", name);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ g_fprintf (file, ">\n");
+ write_callable_info (namespace, (GICallableInfo*)info, file, indent);
+ g_fprintf (file, "%*s</callback>\n", indent, "");
+}
+
+static void
+write_struct_info (const gchar *namespace,
+ GIStructInfo *info,
+ FILE *file)
+{
+ const gchar *name;
+ const gchar *type_name;
+ const gchar *type_init;
+ gboolean deprecated;
+ gint i;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_BOXED)
+ {
+ type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
+ type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
+
+ g_fprintf (file, " <boxed name=\"%s\" type-name=\"%s\" get-type=\"%s\"", name, type_name, type_init);
+ }
+ else
+ g_fprintf (file, " <struct name=\"%s\"", name);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ g_fprintf (file, ">\n");
+
+ for (i = 0; i < g_struct_info_get_n_fields (info); i++)
+ {
+ GIFieldInfo *field = g_struct_info_get_field (info, i);
+ write_field_info (namespace, field, NULL, file);
+ g_base_info_unref ((GIBaseInfo *)field);
+ }
+
+ for (i = 0; i < g_struct_info_get_n_methods (info); i++)
+ {
+ GIFunctionInfo *function = g_struct_info_get_method (info, i);
+ write_function_info (namespace, function, file, 6);
+ g_base_info_unref ((GIBaseInfo *)function);
+ }
+
+ if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_BOXED)
+ g_fprintf (file, " </boxed>\n");
+ else
+ g_fprintf (file, " </struct>\n");
+}
+
+static void
+write_value_info (const gchar *namespace,
+ GIValueInfo *info,
+ FILE *file)
+{
+ const gchar *name;
+ glong value;
+ gboolean deprecated;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ value = g_value_info_get_value (info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ g_fprintf (file, " <member name=\"%s\" value=\"%ld\"", name, value);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ g_fprintf (file, " />\n");
+}
+
+static void
+write_constant_value (const gchar *namespace,
+ GITypeInfo *type,
+ GArgument *value,
+ FILE *file)
+{
+ switch (g_type_info_get_tag (type))
+ {
+ case GI_TYPE_TAG_BOOLEAN:
+ g_fprintf (file, "%d", value->v_boolean);
+ break;
+ case GI_TYPE_TAG_INT8:
+ g_fprintf (file, "%d", value->v_int8);
+ break;
+ case GI_TYPE_TAG_UINT8:
+ g_fprintf (file, "%d", value->v_uint8);
+ break;
+ case GI_TYPE_TAG_INT16:
+ g_fprintf (file, "%" G_GINT16_FORMAT, value->v_int16);
+ break;
+ case GI_TYPE_TAG_UINT16:
+ g_fprintf (file, "%" G_GUINT16_FORMAT, value->v_uint16);
+ break;
+ case GI_TYPE_TAG_INT32:
+ g_fprintf (file, "%" G_GINT32_FORMAT, value->v_int32);
+ break;
+ case GI_TYPE_TAG_UINT32:
+ g_fprintf (file, "%" G_GUINT32_FORMAT, value->v_uint32);
+ break;
+ case GI_TYPE_TAG_INT64:
+ g_fprintf (file, "%" G_GINT64_FORMAT, value->v_int64);
+ break;
+ case GI_TYPE_TAG_UINT64:
+ g_fprintf (file, "%" G_GUINT64_FORMAT, value->v_uint64);
+ break;
+ case GI_TYPE_TAG_INT:
+ g_fprintf (file, "%d", value->v_int);
+ break;
+ case GI_TYPE_TAG_UINT:
+ g_fprintf (file, "%d", value->v_uint);
+ break;
+ case GI_TYPE_TAG_LONG:
+ g_fprintf (file, "%ld", value->v_long);
+ break;
+ case GI_TYPE_TAG_ULONG:
+ g_fprintf (file, "%ld", value->v_ulong);
+ break;
+ case GI_TYPE_TAG_SSIZE:
+ g_fprintf (file, "%zd", value->v_ssize);
+ break;
+ case GI_TYPE_TAG_SIZE:
+ g_fprintf (file, "%zd", value->v_size);
+ break;
+ case GI_TYPE_TAG_FLOAT:
+ g_fprintf (file, "%f", value->v_float);
+ break;
+ case GI_TYPE_TAG_DOUBLE:
+ g_fprintf (file, "%f", value->v_double);
+ break;
+ case GI_TYPE_TAG_UTF8:
+ case GI_TYPE_TAG_FILENAME:
+ g_fprintf (file, "%s", value->v_string);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+write_constant_info (const gchar *namespace,
+ GIConstantInfo *info,
+ FILE *file,
+ gint indent)
+{
+ GITypeInfo *type;
+ const gchar *name;
+ gboolean deprecated;
+ GArgument value;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ g_fprintf (file, "%*s<constant name=\"%s\" type=\"", indent, "", name);
+
+ type = g_constant_info_get_type (info);
+ write_type_info (namespace, type, file);
+ g_fprintf (file, "\" value=\"");
+
+ g_constant_info_get_value (info, &value);
+ write_constant_value (namespace, type, &value, file);
+ g_fprintf (file, "\" />\n");
+
+ g_base_info_unref ((GIBaseInfo *)type);
+}
+
+
+static void
+write_enum_info (const gchar *namespace,
+ GIEnumInfo *info,
+ FILE *file)
+{
+ const gchar *name;
+ const gchar *type_name;
+ const gchar *type_init;
+ gboolean deprecated;
+ gint i;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
+ type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
+
+ if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_ENUM)
+ g_fprintf (file, " <enum ");
+ else
+ g_fprintf (file, " <flags ");
+ g_fprintf (file, "name=\"%s\"", name);
+
+ if (type_init)
+ g_fprintf (file, " type-name=\"%s\" get-type=\"%s\"", type_name, type_init);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ g_fprintf (file, ">\n");
+
+ for (i = 0; i < g_enum_info_get_n_values (info); i++)
+ {
+ GIValueInfo *value = g_enum_info_get_value (info, i);
+ write_value_info (namespace, value, file);
+ g_base_info_unref ((GIBaseInfo *)value);
+ }
+
+ if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_ENUM)
+ g_fprintf (file, " </enum>\n");
+ else
+ g_fprintf (file, " </flags>\n");
+}
+
+static void
+write_signal_info (const gchar *namespace,
+ GISignalInfo *info,
+ FILE *file)
+{
+ GSignalFlags flags;
+ const gchar *name;
+ gboolean deprecated;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ flags = g_signal_info_get_flags (info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ g_fprintf (file, " <signal name=\"%s\"", name);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ if (flags & G_SIGNAL_RUN_FIRST)
+ g_fprintf (file, " when=\"FIRST\"");
+ else if (flags & G_SIGNAL_RUN_LAST)
+ g_fprintf (file, " when=\"LAST\"");
+ else if (flags & G_SIGNAL_RUN_CLEANUP)
+ g_fprintf (file, " when=\"CLEANUP\"");
+
+ if (flags & G_SIGNAL_NO_RECURSE)
+ g_fprintf (file, " no-recurse=\"1\"");
+
+ if (flags & G_SIGNAL_DETAILED)
+ g_fprintf (file, " detailed=\"1\"");
+
+ if (flags & G_SIGNAL_ACTION)
+ g_fprintf (file, " action=\"1\"");
+
+ if (flags & G_SIGNAL_NO_HOOKS)
+ g_fprintf (file, " no-hooks=\"1\"");
+
+ g_fprintf (file, ">\n");
+
+ write_callable_info (namespace, (GICallableInfo*)info, file, 6);
+ g_fprintf (file, " </signal>\n");
+}
+
+static void
+write_vfunc_info (const gchar *namespace,
+ GIVFuncInfo *info,
+ FILE *file)
+{
+ GIVFuncInfoFlags flags;
+ const gchar *name;
+ gboolean deprecated;
+ gint offset;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ flags = g_vfunc_info_get_flags (info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+ offset = g_vfunc_info_get_offset (info);
+
+ g_fprintf (file, " <vfunc name=\"%s\"", name);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ if (flags & GI_VFUNC_MUST_CHAIN_UP)
+ g_fprintf (file, " must-chain-up=\"1\"");
+
+ if (flags & GI_VFUNC_MUST_OVERRIDE)
+ g_fprintf (file, " override=\"always\"");
+ else if (flags & GI_VFUNC_MUST_NOT_OVERRIDE)
+ g_fprintf (file, " override=\"never\"");
+
+ g_fprintf (file, " offset=\"%d\"", offset);
+ g_fprintf (file, ">\n");
+
+ write_callable_info (namespace, (GICallableInfo*)info, file, 6);
+ g_fprintf (file, " </vfunc>\n");
+}
+
+static void
+write_property_info (const gchar *namespace,
+ GIPropertyInfo *info,
+ FILE *file)
+{
+ GParamFlags flags;
+ const gchar *name;
+ gboolean deprecated;
+ GITypeInfo *type;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ flags = g_property_info_get_flags (info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ g_fprintf (file, " <property name=\"%s\"", name);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ if (flags & G_PARAM_READABLE)
+ g_fprintf (file, " readable=\"1\"");
+ else
+ g_fprintf (file, " readable=\"0\"");
+
+ if (flags & G_PARAM_WRITABLE)
+ g_fprintf (file, " writable=\"1\"");
+ else
+ g_fprintf (file, " writable=\"0\"");
+
+ if (flags & G_PARAM_CONSTRUCT)
+ g_fprintf (file, " construct=\"1\"");
+
+ if (flags & G_PARAM_CONSTRUCT_ONLY)
+ g_fprintf (file, " construct-only=\"1\"");
+
+ type = g_property_info_get_type (info);
+ g_fprintf (file, " type=\"");
+ write_type_info (namespace, type, file);
+ g_fprintf (file, "\"");
+
+ g_fprintf (file, " />\n");
+}
+
+static void
+write_object_info (const gchar *namespace,
+ GIObjectInfo *info,
+ FILE *file)
+{
+ const gchar *name;
+ const gchar *type_name;
+ const gchar *type_init;
+ gboolean deprecated;
+ GIObjectInfo *pnode;
+ gint i;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
+ type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
+ g_fprintf (file, " <object name=\"%s\"", name);
+
+ pnode = g_object_info_get_parent (info);
+ if (pnode)
+ {
+ g_fprintf (file, " parent=\"");
+ write_type_name (namespace, (GIBaseInfo *)pnode, file);
+ g_fprintf (file, "\"" );
+ g_base_info_unref ((GIBaseInfo *)pnode);
+ }
+
+ g_fprintf (file, " type-name=\"%s\" get-type=\"%s\"", type_name, type_init);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ g_fprintf (file, ">\n");
+
+ if (g_object_info_get_n_interfaces (info) > 0)
+ {
+ g_fprintf (file, " <implements>\n");
+ for (i = 0; i < g_object_info_get_n_interfaces (info); i++)
+ {
+ GIInterfaceInfo *imp = g_object_info_get_interface (info, i);
+ g_fprintf (file, " <interface name=\"");
+ write_type_name (namespace, (GIBaseInfo*)imp, file);
+ g_fprintf (file,"\" />\n");
+ g_base_info_unref ((GIBaseInfo*)imp);
+ }
+ g_fprintf (file, " </implements>\n");
+ }
+
+ for (i = 0; i < g_object_info_get_n_fields (info); i++)
+ {
+ GIFieldInfo *field = g_object_info_get_field (info, i);
+ write_field_info (namespace, field, NULL, file);
+ g_base_info_unref ((GIBaseInfo *)field);
+ }
+
+ for (i = 0; i < g_object_info_get_n_methods (info); i++)
+ {
+ GIFunctionInfo *function = g_object_info_get_method (info, i);
+ write_function_info (namespace, function, file, 6);
+ g_base_info_unref ((GIBaseInfo *)function);
+ }
+
+ for (i = 0; i < g_object_info_get_n_properties (info); i++)
+ {
+ GIPropertyInfo *prop = g_object_info_get_property (info, i);
+ write_property_info (namespace, prop, file);
+ g_base_info_unref ((GIBaseInfo *)prop);
+ }
+
+ for (i = 0; i < g_object_info_get_n_signals (info); i++)
+ {
+ GISignalInfo *signal = g_object_info_get_signal (info, i);
+ write_signal_info (namespace, signal, file);
+ g_base_info_unref ((GIBaseInfo *)signal);
+ }
+
+ for (i = 0; i < g_object_info_get_n_vfuncs (info); i++)
+ {
+ GIVFuncInfo *vfunc = g_object_info_get_vfunc (info, i);
+ write_vfunc_info (namespace, vfunc, file);
+ g_base_info_unref ((GIBaseInfo *)vfunc);
+ }
+
+ for (i = 0; i < g_object_info_get_n_constants (info); i++)
+ {
+ GIConstantInfo *constant = g_object_info_get_constant (info, i);
+ write_constant_info (namespace, constant, file, 6);
+ g_base_info_unref ((GIBaseInfo *)constant);
+ }
+
+ g_fprintf (file, " </object>\n");
+}
+
+static void
+write_interface_info (const gchar *namespace,
+ GIInterfaceInfo *info,
+ FILE *file)
+{
+ const gchar *name;
+ const gchar *type_name;
+ const gchar *type_init;
+ gboolean deprecated;
+ gint i;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
+ type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
+ g_fprintf (file, " <interface name=\"%s\" type-name=\"%s\" get-type=\"%s\"",
+ name, type_name, type_init);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ g_fprintf (file, ">\n");
+
+ if (g_interface_info_get_n_prerequisites (info) > 0)
+ {
+ g_fprintf (file, " <requires>\n");
+ for (i = 0; i < g_interface_info_get_n_prerequisites (info); i++)
+ {
+ GIBaseInfo *req = g_interface_info_get_prerequisite (info, i);
+
+ if (g_base_info_get_type (req) == GI_INFO_TYPE_INTERFACE)
+ g_fprintf (file, " <interface name=\"");
+ else
+ g_fprintf (file, " <object name=\"");
+ write_type_name (namespace, req, file);
+ g_fprintf (file, "\" />\n");
+ g_base_info_unref (req);
+ }
+ g_fprintf (file, " </requires>\n");
+ }
+
+ for (i = 0; i < g_interface_info_get_n_methods (info); i++)
+ {
+ GIFunctionInfo *function = g_interface_info_get_method (info, i);
+ write_function_info (namespace, function, file, 6);
+ g_base_info_unref ((GIBaseInfo *)function);
+ }
+
+ for (i = 0; i < g_interface_info_get_n_properties (info); i++)
+ {
+ GIPropertyInfo *prop = g_interface_info_get_property (info, i);
+ write_property_info (namespace, prop, file);
+ g_base_info_unref ((GIBaseInfo *)prop);
+ }
+
+ for (i = 0; i < g_interface_info_get_n_signals (info); i++)
+ {
+ GISignalInfo *signal = g_interface_info_get_signal (info, i);
+ write_signal_info (namespace, signal, file);
+ g_base_info_unref ((GIBaseInfo *)signal);
+ }
+
+ for (i = 0; i < g_interface_info_get_n_vfuncs (info); i++)
+ {
+ GIVFuncInfo *vfunc = g_interface_info_get_vfunc (info, i);
+ write_vfunc_info (namespace, vfunc, file);
+ g_base_info_unref ((GIBaseInfo *)vfunc);
+ }
+
+ for (i = 0; i < g_interface_info_get_n_constants (info); i++)
+ {
+ GIConstantInfo *constant = g_interface_info_get_constant (info, i);
+ write_constant_info (namespace, constant, file, 6);
+ g_base_info_unref ((GIBaseInfo *)constant);
+ }
+
+ g_fprintf (file, " </interface>\n");
+}
+
+static void
+write_error_domain_info (const gchar *namespace,
+ GIErrorDomainInfo *info,
+ FILE *file)
+{
+ GIBaseInfo *enum_;
+ const gchar *name, *quark;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ quark = g_error_domain_info_get_quark (info);
+ enum_ = (GIBaseInfo *)g_error_domain_info_get_codes (info);
+ g_fprintf (file,
+ " <errordomain name=\"%s\" get-quark=\"%s\" codes=\"",
+ name, quark);
+ write_type_name (namespace, enum_, file);
+ g_fprintf (file, "\" />\n");
+ g_base_info_unref (enum_);
+}
+
+static void
+write_union_info (const gchar *namespace,
+ GIUnionInfo *info,
+ FILE *file)
+{
+ const gchar *name;
+ const gchar *type_name;
+ const gchar *type_init;
+ gboolean deprecated;
+ gint i;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
+ type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
+
+ g_fprintf (file, " <union name=\"%s\"", name);
+
+ if (type_name)
+ g_fprintf (file, " type-name=\"%s\" get-type=\"%s\"", type_name, type_init);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ g_fprintf (file, ">\n");
+
+ if (g_union_info_is_discriminated (info))
+ {
+ gint offset;
+ GITypeInfo *type;
+
+ offset = g_union_info_get_discriminator_offset (info);
+ type = g_union_info_get_discriminator_type (info);
+
+ g_fprintf (file, " <discriminator offset=\"%d\" type=\"", offset);
+ write_type_info (namespace, type, file);
+ g_fprintf (file, "\" />\n");
+ g_base_info_unref ((GIBaseInfo *)type);
+ }
+
+ for (i = 0; i < g_union_info_get_n_fields (info); i++)
+ {
+ GIFieldInfo *field = g_union_info_get_field (info, i);
+ GIConstantInfo *constant = g_union_info_get_discriminator (info, i);
+ write_field_info (namespace, field, constant, file);
+ g_base_info_unref ((GIBaseInfo *)field);
+ if (constant)
+ g_base_info_unref ((GIBaseInfo *)constant);
+ }
+
+ for (i = 0; i < g_union_info_get_n_methods (info); i++)
+ {
+ GIFunctionInfo *function = g_union_info_get_method (info, i);
+ write_function_info (namespace, function, file, 6);
+ g_base_info_unref ((GIBaseInfo *)function);
+ }
+
+ g_fprintf (file, " </union>\n");
+}
+
+static void
+write_repository (GIRepository *repository,
+ gboolean needs_prefix)
+{
+ FILE *file;
+ gchar **namespaces;
+ gchar *ns;
+ gint i, j;
+
+ namespaces = g_irepository_get_namespaces (repository);
+
+ if (output == NULL)
+ file = stdout;
+ else
+ {
+ gchar *filename;
+
+ if (needs_prefix)
+ filename = g_strdup_printf ("%s-%s", namespaces[0], output);
+ else
+ filename = g_strdup (output);
+ file = g_fopen (filename, "w");
+
+ if (file == NULL)
+ {
+ g_fprintf (stderr, "failed to open '%s': %s\n",
+ filename, g_strerror (errno));
+ g_free (filename);
+
+ return;
+ }
+
+ g_free (filename);
+ }
+
+ g_fprintf (file, "<?xml version=\"1.0\"?>\n");
+ g_fprintf (file, "<api version=\"1.0\">\n");
+
+ for (i = 0; namespaces[i]; i++)
+ {
+ const gchar *shared_library;
+ ns = namespaces[i];
+ shared_library = g_irepository_get_shared_library (repository, ns);
+ if (shared_library)
+ g_fprintf (file, " <namespace name=\"%s\" shared-library=\"%s\">\n",
+ ns, shared_library);
+ else
+ g_fprintf (file, " <namespace name=\"%s\">\n", ns);
+
+ for (j = 0; j < g_irepository_get_n_infos (repository, ns); j++)
+ {
+ GIBaseInfo *info = g_irepository_get_info (repository, ns, j);
+ switch (g_base_info_get_type (info))
+ {
+ case GI_INFO_TYPE_FUNCTION:
+ write_function_info (ns, (GIFunctionInfo *)info, file, 4);
+ break;
+
+ case GI_INFO_TYPE_CALLBACK:
+ write_callback_info (ns, (GICallbackInfo *)info, file, 4);
+ break;
+
+ case GI_INFO_TYPE_STRUCT:
+ case GI_INFO_TYPE_BOXED:
+ write_struct_info (ns, (GIStructInfo *)info, file);
+ break;
+
+ case GI_INFO_TYPE_UNION:
+ write_union_info (ns, (GIUnionInfo *)info, file);
+ break;
+
+ case GI_INFO_TYPE_ENUM:
+ case GI_INFO_TYPE_FLAGS:
+ write_enum_info (ns, (GIEnumInfo *)info, file);
+ break;
+
+ case GI_INFO_TYPE_CONSTANT:
+ write_constant_info (ns, (GIConstantInfo *)info, file, 4);
+ break;
+
+ case GI_INFO_TYPE_OBJECT:
+ write_object_info (ns, (GIObjectInfo *)info, file);
+ break;
+
+ case GI_INFO_TYPE_INTERFACE:
+ write_interface_info (ns, (GIInterfaceInfo *)info, file);
+ break;
+
+ case GI_INFO_TYPE_ERROR_DOMAIN:
+ write_error_domain_info (ns, (GIErrorDomainInfo *)info, file);
+ break;
+
+ default:
+ g_error ("unknown info type %d\n", g_base_info_get_type (info));
+ }
+
+ g_base_info_unref (info);
+ }
+
+ g_fprintf (file, " </namespace>\n");
+ }
+
+ g_fprintf (file, "</api>\n");
+
+ if (output != NULL)
+ fclose (file);
+
+ g_strfreev (namespaces);
+}
+
+static GOptionEntry options[] =
+{
+ { "raw", 0, 0, G_OPTION_ARG_NONE, &raw, "handle raw metadata", NULL },
+ { "output", 'o', 0, G_OPTION_ARG_FILENAME, &output, "output file", "FILE" },
+ { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &input, NULL, NULL },
+ { NULL, }
+};
+
+static const guchar *
+load_metadata (const gchar *filename,
+ GModule **dlhandle,
+ gsize *len)
+{
+ guchar *metadata;
+ gsize *metadata_size;
+ GModule *handle;
+
+ handle = g_module_open (filename, G_MODULE_BIND_LOCAL|G_MODULE_BIND_LAZY);
+ if (!g_module_symbol (handle, "_G_METADATA", (gpointer *) &metadata))
+ {
+ g_printerr ("Could not load metadata from '%s': %s\n",
+ filename, g_module_error ());
+ return NULL;
+ }
+
+ if (!g_module_symbol (handle, "_G_METADATA_SIZE", (gpointer *) &metadata_size))
+ {
+ g_printerr ("Could not load metadata from '%s': %s\n",
+ filename, g_module_error ());
+ return NULL;
+ }
+
+ *len = *metadata_size;
+
+ if (dlhandle)
+ *dlhandle = handle;
+
+ return metadata;
+}
+
+int
+main (int argc, char *argv[])
+{
+ GOptionContext *context;
+ GError *error = NULL;
+ gboolean needs_prefix;
+ gint i;
+ GMetadata *data;
+
+ g_type_init ();
+
+ g_metadata_check_sanity ();
+
+ context = g_option_context_new ("");
+ g_option_context_add_main_entries (context, options, NULL);
+ g_option_context_parse (context, &argc, &argv, &error);
+
+ if (!input)
+ {
+ g_fprintf (stderr, "no input files\n");
+
+ return 1;
+ }
+
+ for (i = 0; input[i]; i++)
+ {
+ GModule *dlhandle = NULL;
+ const guchar *metadata;
+ gsize len;
+
+ if (raw)
+ {
+ if (!g_file_get_contents (input[i], (gchar **)&metadata, &len, &error))
+ {
+ g_fprintf (stderr, "failed to read '%s': %s\n",
+ input[i], error->message);
+ g_clear_error (&error);
+ continue;
+ }
+ }
+ else
+ {
+ metadata = load_metadata (input[i], &dlhandle, &len);
+ if (!metadata)
+ {
+ g_fprintf (stderr, "failed to load metadata from '%s'\n",
+ input[i]);
+ continue;
+ }
+ }
+
+ if (input[i + 1] && output)
+ needs_prefix = TRUE;
+ else
+ needs_prefix = FALSE;
+
+ data = g_metadata_new_from_const_memory (metadata, len);
+ {
+ GError *error = NULL;
+ if (!g_metadata_validate (data, &error)) {
+ g_printerr ("metadata not valid: %s\n", error->message);
+ g_clear_error (&error);
+ }
+ }
+ g_irepository_register (g_irepository_get_default (), data);
+ write_repository (g_irepository_get_default (), needs_prefix);
+ g_irepository_unregister (g_irepository_get_default (),
+ g_metadata_get_namespace (data));
+
+ if (dlhandle)
+ {
+ g_module_close (dlhandle);
+ dlhandle = NULL;
+ }
+
+ /* when writing to stdout, stop after the first module */
+ if (input[i + 1] && !output)
+ {
+ g_fprintf (stderr, "warning, %d modules omitted\n",
+ g_strv_length (input) - 1);
+
+ break;
+ }
+ }
+
+ return 0;
+}