diff options
author | Rob Taylor <rob.taylor@codethink.co.uk> | 2008-02-08 15:31:03 +0000 |
---|---|---|
committer | Robert James Taylor <robtaylor@src.gnome.org> | 2008-02-08 15:31:03 +0000 |
commit | b935261f387dffa2c7006fe1be04820004810e87 (patch) | |
tree | 0c077cee05c725e1e56309374a1ceea8d8881b7d /tools/generate.c | |
parent | c6c15af80d8a6d34e5c77d3111c638126edb3d45 (diff) | |
download | gobject-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.c | 1223 |
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; +} |