summaryrefslogtreecommitdiff
path: root/gobject-introspection
diff options
context:
space:
mode:
authorJürg Billeter <j@bitron.ch>2007-05-02 09:42:00 +0000
committerJürg Billeter <juergbi@src.gnome.org>2007-05-02 09:42:00 +0000
commitf8387ad143f1884f8f5f89bd5389605624f4c34f (patch)
treee75e563fc9535200ec146af72962e80778359ae4 /gobject-introspection
parent9db973114ee1449c1764404163ecc8294f8e73d2 (diff)
downloadvala-f8387ad143f1884f8f5f89bd5389605624f4c34f.tar.gz
Move contents of vala-pkg to trunk
2007-05-02 Jürg Billeter <j@bitron.ch> * Move contents of vala-pkg to trunk svn path=/trunk/; revision=300
Diffstat (limited to 'gobject-introspection')
-rw-r--r--gobject-introspection/Makefile.am25
-rw-r--r--gobject-introspection/gidl.vala260
-rw-r--r--gobject-introspection/gidlmodule.c208
-rw-r--r--gobject-introspection/gidlmodule.h47
-rw-r--r--gobject-introspection/gidlnode.c1992
-rw-r--r--gobject-introspection/gidlnode.h331
-rw-r--r--gobject-introspection/gidlparser.c2036
-rw-r--r--gobject-introspection/gidlparser.h38
-rw-r--r--gobject-introspection/gmetadata.h539
9 files changed, 5476 insertions, 0 deletions
diff --git a/gobject-introspection/Makefile.am b/gobject-introspection/Makefile.am
new file mode 100644
index 000000000..7196fe6e3
--- /dev/null
+++ b/gobject-introspection/Makefile.am
@@ -0,0 +1,25 @@
+NULL =
+
+INCLUDES = \
+ $(GLIB_CFLAGS) \
+ $(NULL)
+
+noinst_LTLIBRARIES = \
+ libgidl.la \
+ $(NULL)
+
+libgidl_la_SOURCES = \
+ gidlmodule.c \
+ gidlmodule.h \
+ gidlnode.c \
+ gidlnode.h \
+ gidlparser.c \
+ gidlparser.h \
+ gmetadata.h \
+ $(NULL)
+
+libgidl_la_LIBADD = \
+ $(GLIB_LIBS) \
+ $(NULL)
+
+EXTRA_DIST = gidl.vala
diff --git a/gobject-introspection/gidl.vala b/gobject-introspection/gidl.vala
new file mode 100644
index 000000000..2572b3212
--- /dev/null
+++ b/gobject-introspection/gidl.vala
@@ -0,0 +1,260 @@
+/* gidl.vala
+ *
+ * Copyright (C) 2006 Jürg Billeter
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Jürg Billeter <j@bitron.ch>
+ */
+
+[CCode (cprefix = "G", lower_case_cprefix = "g_", cheader_filename = "glib.h")]
+namespace GLib {
+ [CCode (cheader_filename = "gidlparser.h")]
+ public struct Idl {
+ public static ref List<IdlModule> parse_file (string! filename, out Error error);
+ }
+
+ [CCode (cheader_filename = "gidlmodule.h")]
+ [ReferenceType (free_function = "g_idl_module_free")]
+ public struct IdlModule {
+ public string name;
+ public List<IdlNode> entries;
+ }
+
+ [CCode (cprefix = "G_IDL_NODE_", cheader_filename = "gidlnode.h")]
+ public enum IdlNodeTypeId {
+ INVALID,
+ FUNCTION,
+ CALLBACK,
+ STRUCT,
+ BOXED,
+ ENUM,
+ FLAGS,
+ OBJECT,
+ INTERFACE,
+ CONSTANT,
+ ERROR_DOMAIN,
+ UNION,
+ PARAM,
+ TYPE,
+ PROPERTY,
+ SIGNAL,
+ VALUE,
+ VFUNC,
+ FIELD,
+ XREF
+ }
+
+ [CCode (cheader_filename = "gidlnode.h")]
+ [ReferenceType (free_function = "g_idl_node_free")]
+ public struct IdlNode {
+ public IdlNodeTypeId type;
+ public string name;
+ }
+
+ [CCode (cheader_filename = "gidlnode.h")]
+ [ReferenceType (free_function = "g_idl_node_free")]
+ public struct IdlNodeFunction {
+ public bool deprecated;
+
+ public bool is_method;
+ public bool is_setter;
+ public bool is_getter;
+ public bool is_constructor;
+ public bool wraps_vfunc;
+
+ public string symbol;
+
+ public IdlNodeParam result;
+ public List<IdlNodeParam> parameters;
+ }
+
+ [CCode (cheader_filename = "gidlnode.h")]
+ [ReferenceType (free_function = "g_idl_node_free")]
+ public struct IdlNodeSignal {
+ public bool deprecated;
+
+ public bool run_first;
+ public bool run_last;
+ public bool run_cleanup;
+ public bool no_recurse;
+ public bool detailed;
+ public bool action;
+ public bool no_hooks;
+
+ public bool has_class_closure;
+ public bool true_stops_emit;
+
+ public int class_closure;
+
+ public List<IdlNodeParam> parameters;
+ public IdlNodeParam result;
+ }
+
+ [CCode (cheader_filename = "gidlnode.h")]
+ [ReferenceType (free_function = "g_idl_node_free")]
+ public struct IdlNodeBoxed {
+ public bool deprecated;
+
+ public string gtype_name;
+ public string gtype_init;
+
+ public List<IdlNode> members;
+ }
+
+ [CCode (cheader_filename = "gidlnode.h")]
+ [ReferenceType (free_function = "g_idl_node_free")]
+ public struct IdlNodeEnum {
+ public bool deprecated;
+
+ public string gtype_name;
+ public string gtype_init;
+
+ public List<IdlNode> values;
+ }
+
+ [CCode (cheader_filename = "gidlnode.h")]
+ [ReferenceType (free_function = "g_idl_node_free")]
+ public struct IdlNodeField {
+ public bool readable;
+ public bool writable;
+ public int bits;
+ public int offset;
+
+ public IdlNodeType type;
+ }
+
+ [CCode (cheader_filename = "gidlnode.h")]
+ [ReferenceType (free_function = "g_idl_node_free")]
+ public struct IdlNodeConstant {
+ public bool deprecated;
+
+ public IdlNodeType type;
+
+ public string value;
+ }
+
+ [CCode (cheader_filename = "gidlnode.h")]
+ [ReferenceType (free_function = "g_idl_node_free")]
+ public struct IdlNodeInterface {
+ public bool deprecated;
+
+ public string gtype_name;
+ public string gtype_init;
+
+ public string parent;
+
+ public List<string> interfaces;
+ public List<string> prerequisites;
+
+ public List<IdlNode> members;
+ }
+
+ [CCode (cheader_filename = "gidlnode.h")]
+ [ReferenceType (free_function = "g_idl_node_free")]
+ public struct IdlNodeParam {
+ public bool @in;
+ public bool @out;
+ public bool dipper;
+ public bool optional;
+ public bool retval;
+ public bool null_ok;
+ public bool transfer;
+ public bool shallow_transfer;
+
+ public IdlNodeType type;
+ }
+
+ [CCode (cheader_filename = "gidlnode.h")]
+ [ReferenceType (free_function = "g_idl_node_free")]
+ public struct IdlNodeProperty {
+ public bool deprecated;
+
+ public string name;
+
+ public bool readable;
+ public bool writable;
+ public bool @construct;
+ public bool construct_only;
+
+ public IdlNodeType type;
+ }
+
+ [CCode (cheader_filename = "gidlnode.h")]
+ [ReferenceType (free_function = "g_idl_node_free")]
+ public struct IdlNodeStruct {
+ public bool deprecated;
+
+ public List<IdlNode> members;
+ }
+
+ [CCode (cheader_filename = "gidlnode.h")]
+ [ReferenceType (free_function = "g_idl_node_free")]
+ public struct IdlNodeType {
+ public bool is_pointer;
+ public bool is_basic;
+ public bool is_array;
+ public bool is_glist;
+ public bool is_gslist;
+ public bool is_ghashtable;
+ public bool is_interface;
+ public bool is_error;
+ public TypeTag tag;
+
+ public string unparsed;
+
+ public bool zero_terminated;
+ public bool has_length;
+ public int length;
+
+ public IdlNodeType parameter_type1;
+ public IdlNodeType parameter_type2;
+
+ public string @interface;
+ public string[] errors;
+ }
+
+ [CCode (cprefix = "TYPE_TAG_", cheader_filename = "gmetadata.h")]
+ public enum TypeTag
+ {
+ VOID,
+ BOOLEAN,
+ INT8,
+ UINT8,
+ INT16,
+ UINT16,
+ INT32,
+ UINT32,
+ INT64,
+ UINT64,
+ INT,
+ UINT,
+ LONG,
+ ULONG,
+ SSIZE,
+ SIZE,
+ FLOAT,
+ DOUBLE,
+ UTF8,
+ FILENAME,
+ ARRAY,
+ INTERFACE,
+ LIST,
+ SLIST,
+ HASH,
+ ERROR
+ }
+}
diff --git a/gobject-introspection/gidlmodule.c b/gobject-introspection/gidlmodule.c
new file mode 100644
index 000000000..2d4929e0a
--- /dev/null
+++ b/gobject-introspection/gidlmodule.c
@@ -0,0 +1,208 @@
+/* GObject introspection: Metadata creation
+ *
+ * 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 <stdio.h>
+#include <string.h>
+
+#include "gidlmodule.h"
+#include "gidlnode.h"
+#include "gmetadata.h"
+
+#define ALIGN_VALUE(this, boundary) \
+ (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
+
+
+GIdlModule *
+g_idl_module_new (const gchar *name)
+{
+ GIdlModule *module;
+
+ module = g_new (GIdlModule, 1);
+
+ module->name = g_strdup (name);
+ module->entries = NULL;
+
+ return module;
+}
+
+void
+g_idl_module_free (GIdlModule *module)
+{
+ GList *e;
+
+ g_free (module->name);
+
+ for (e = module->entries; e; e = e->next)
+ g_idl_node_free ((GIdlNode *)e->data);
+
+ g_list_free (module->entries);
+
+ g_free (module);
+}
+
+void
+g_idl_module_build_metadata (GIdlModule *module,
+ GList *modules,
+ guchar **metadata,
+ gsize *length)
+{
+ gint i;
+ GList *e;
+ Header *header;
+ DirEntry *entry;
+ guint32 header_size;
+ guint32 dir_size;
+ guint32 n_entries;
+ guint32 n_local_entries;
+ guint32 size, offset, offset2, old_offset;
+ GHashTable *strings;
+ GHashTable *types;
+ guchar *data;
+
+ header_size = ALIGN_VALUE (sizeof (Header), 4);
+ n_local_entries = g_list_length (module->entries);
+
+ restart:
+ init_stats ();
+ strings = g_hash_table_new (g_str_hash, g_str_equal);
+ types = g_hash_table_new (g_str_hash, g_str_equal);
+ n_entries = g_list_length (module->entries);
+
+ g_message ("%d entries (%d local)\n", n_entries, n_local_entries);
+
+ dir_size = n_entries * 12;
+ size = header_size + dir_size;
+
+ size += ALIGN_VALUE (strlen (module->name) + 1, 4);
+
+ for (e = module->entries; e; e = e->next)
+ {
+ GIdlNode *node = e->data;
+
+ size += g_idl_node_get_full_size (node);
+ }
+
+ g_message ("allocating %d bytes (%d header, %d directory, %d entries)\n",
+ size, header_size, dir_size, size - header_size - dir_size);
+
+ data = g_malloc0 (size);
+
+ /* fill in header */
+ header = (Header *)data;
+ memcpy (header, G_IDL_MAGIC, 16);
+ header->major_version = 1;
+ header->minor_version = 0;
+ header->reserved = 0;
+ header->n_entries = n_entries;
+ header->n_local_entries = n_local_entries;
+ header->n_annotations = 0;
+ header->annotations = 0; /* filled in later */
+ header->size = 0; /* filled in later */
+ header->namespace = write_string (module->name, strings, data, &header_size);
+ header->directory = ALIGN_VALUE (header_size, 4);
+ header->entry_blob_size = 12;
+ header->function_blob_size = 16;
+ header->callback_blob_size = 12;
+ header->signal_blob_size = 12;
+ header->vfunc_blob_size = 16;
+ header->arg_blob_size = 12;
+ header->property_blob_size = 12;
+ header->field_blob_size = 12;
+ header->value_blob_size = 12;
+ header->constant_blob_size = 20;
+ header->error_domain_blob_size = 16;
+ header->annotation_blob_size = 12;
+ header->signature_blob_size = 8;
+ header->enum_blob_size = 20;
+ header->struct_blob_size = 20;
+ header->object_blob_size = 32;
+ header->interface_blob_size = 28;
+ header->union_blob_size = 28;
+
+ /* fill in directory and content */
+ entry = (DirEntry *)&data[header->directory];
+
+ offset2 = header->directory + dir_size;
+
+ for (e = module->entries, i = 0; e; e = e->next, i++)
+ {
+ GIdlNode *node = e->data;
+
+ if (strchr (node->name, '.'))
+ {
+ g_error ("Names may not contain '.'");
+ }
+
+ /* we picked up implicit xref nodes, start over */
+ if (i == n_entries)
+ {
+ g_message ("Found implicit cross references, starting over");
+
+ g_hash_table_destroy (strings);
+ g_hash_table_destroy (types);
+ strings = NULL;
+
+ g_free (data);
+ data = NULL;
+
+ goto restart;
+ }
+
+ offset = offset2;
+
+ if (node->type == G_IDL_NODE_XREF)
+ {
+ entry->blob_type = 0;
+ entry->local = FALSE;
+ entry->offset = write_string (((GIdlNodeXRef*)node)->namespace, strings, data, &offset2);
+ entry->name = write_string (node->name, strings, data, &offset2);
+ }
+ else
+ {
+ old_offset = offset;
+ offset2 = offset + g_idl_node_get_size (node);
+
+ entry->blob_type = node->type;
+ entry->local = TRUE;
+ entry->offset = offset;
+ entry->name = write_string (node->name, strings, data, &offset2);
+
+ g_idl_node_build_metadata (node, module, modules,
+ strings, types, data, &offset, &offset2);
+
+ if (offset2 > old_offset + g_idl_node_get_full_size (node))
+ g_error ("left a hole of %d bytes\n", offset2 - old_offset - g_idl_node_get_full_size (node));
+ }
+
+ entry++;
+ }
+
+ dump_stats ();
+ g_hash_table_destroy (strings);
+ g_hash_table_destroy (types);
+
+ header->annotations = offset2;
+
+ g_message ("reallocating to %d bytes", offset2);
+
+ *metadata = g_realloc (data, offset2);
+ *length = header->size = offset2;
+}
+
diff --git a/gobject-introspection/gidlmodule.h b/gobject-introspection/gidlmodule.h
new file mode 100644
index 000000000..17135764c
--- /dev/null
+++ b/gobject-introspection/gidlmodule.h
@@ -0,0 +1,47 @@
+/* GObject introspection: Parsed IDL
+ *
+ * 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.
+ */
+
+#ifndef __G_IDL_MODULE_H__
+#define __G_IDL_MODULE_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _GIdlModule GIdlModule;
+
+struct _GIdlModule
+{
+ gchar *name;
+ GList *entries;
+};
+
+GIdlModule *g_idl_module_new (const gchar *name);
+void g_idl_module_free (GIdlModule *module);
+
+void g_idl_module_build_metadata (GIdlModule *module,
+ GList *modules,
+ guchar **metadata,
+ gsize *length);
+
+G_END_DECLS
+
+#endif /* __G_IDL_MODULE_H__ */
diff --git a/gobject-introspection/gidlnode.c b/gobject-introspection/gidlnode.c
new file mode 100644
index 000000000..bbde2a005
--- /dev/null
+++ b/gobject-introspection/gidlnode.c
@@ -0,0 +1,1992 @@
+/* GObject introspection: Metadata creation
+ *
+ * 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 <stdio.h>
+#include <string.h>
+
+#include "gidlmodule.h"
+#include "gidlnode.h"
+#include "gmetadata.h"
+
+static gulong string_count = 0;
+static gulong unique_string_count = 0;
+static gulong string_size = 0;
+static gulong unique_string_size = 0;
+static gulong types_count = 0;
+static gulong unique_types_count = 0;
+
+void
+init_stats (void)
+{
+ string_count = 0;
+ unique_string_count = 0;
+ string_size = 0;
+ unique_string_size = 0;
+ types_count = 0;
+ unique_types_count = 0;
+}
+
+void
+dump_stats (void)
+{
+ g_message ("%d strings (%d before sharing), %d bytes (%d before sharing)",
+ unique_string_count, string_count, unique_string_size, string_size);
+ g_message ("%d types (%d before sharing)", unique_types_count, types_count);
+}
+
+#define ALIGN_VALUE(this, boundary) \
+ (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
+
+
+GIdlNode *
+g_idl_node_new (GIdlNodeTypeId type)
+{
+ GIdlNode *node = NULL;
+
+ switch (type)
+ {
+ case G_IDL_NODE_FUNCTION:
+ node = g_malloc0 (sizeof (GIdlNodeFunction));
+ break;
+
+ case G_IDL_NODE_PARAM:
+ node = g_malloc0 (sizeof (GIdlNodeParam));
+ break;
+
+ case G_IDL_NODE_TYPE:
+ node = g_malloc0 (sizeof (GIdlNodeType));
+ break;
+
+ case G_IDL_NODE_OBJECT:
+ case G_IDL_NODE_INTERFACE:
+ node = g_malloc0 (sizeof (GIdlNodeInterface));
+ break;
+
+ case G_IDL_NODE_SIGNAL:
+ node = g_malloc0 (sizeof (GIdlNodeSignal));
+ break;
+
+ case G_IDL_NODE_PROPERTY:
+ node = g_malloc0 (sizeof (GIdlNodeProperty));
+ break;
+
+ case G_IDL_NODE_VFUNC:
+ node = g_malloc0 (sizeof (GIdlNodeFunction));
+ break;
+
+ case G_IDL_NODE_FIELD:
+ node = g_malloc0 (sizeof (GIdlNodeField));
+ break;
+
+ case G_IDL_NODE_ENUM:
+ case G_IDL_NODE_FLAGS:
+ node = g_malloc0 (sizeof (GIdlNodeEnum));
+ break;
+
+ case G_IDL_NODE_BOXED:
+ node = g_malloc0 (sizeof (GIdlNodeBoxed));
+ break;
+
+ case G_IDL_NODE_STRUCT:
+ node = g_malloc0 (sizeof (GIdlNodeStruct));
+ break;
+
+ case G_IDL_NODE_VALUE:
+ node = g_malloc0 (sizeof (GIdlNodeValue));
+ break;
+
+ case G_IDL_NODE_CONSTANT:
+ node = g_malloc0 (sizeof (GIdlNodeConstant));
+ break;
+
+ case G_IDL_NODE_ERROR_DOMAIN:
+ node = g_malloc0 (sizeof (GIdlNodeErrorDomain));
+ break;
+
+ case G_IDL_NODE_XREF:
+ node = g_malloc0 (sizeof (GIdlNodeXRef));
+ break;
+
+ case G_IDL_NODE_UNION:
+ node = g_malloc0 (sizeof (GIdlNodeUnion));
+ break;
+
+ default:
+ g_error ("Unhandled node type %d\n", type);
+ break;
+ }
+
+ node->type = type;
+
+ return node;
+}
+
+void
+g_idl_node_free (GIdlNode *node)
+{
+ GList *l;
+
+ if (node == NULL)
+ return;
+
+ switch (node->type)
+ {
+ case G_IDL_NODE_FUNCTION:
+ case G_IDL_NODE_CALLBACK:
+ {
+ GIdlNodeFunction *function = (GIdlNodeFunction *)node;
+
+ g_free (node->name);
+ g_free (function->symbol);
+ g_idl_node_free ((GIdlNode *)function->result);
+ for (l = function->parameters; l; l = l->next)
+ g_idl_node_free ((GIdlNode *)l->data);
+ g_list_free (function->parameters);
+ }
+ break;
+
+ case G_IDL_NODE_TYPE:
+ {
+ GIdlNodeType *type = (GIdlNodeType *)node;
+
+ g_free (node->name);
+ g_idl_node_free ((GIdlNode *)type->parameter_type1);
+ g_idl_node_free ((GIdlNode *)type->parameter_type2);
+
+ g_free (type->interface);
+ g_strfreev (type->errors);
+
+ }
+ break;
+
+ case G_IDL_NODE_PARAM:
+ {
+ GIdlNodeParam *param = (GIdlNodeParam *)node;
+
+ g_free (node->name);
+ g_idl_node_free ((GIdlNode *)param->type);
+ }
+ break;
+
+ case G_IDL_NODE_PROPERTY:
+ {
+ GIdlNodeProperty *property = (GIdlNodeProperty *)node;
+
+ g_free (node->name);
+ g_idl_node_free ((GIdlNode *)property->type);
+ }
+ break;
+
+ case G_IDL_NODE_SIGNAL:
+ {
+ GIdlNodeSignal *signal = (GIdlNodeSignal *)node;
+
+ g_free (node->name);
+ for (l = signal->parameters; l; l = l->next)
+ g_idl_node_free ((GIdlNode *)l->data);
+ g_list_free (signal->parameters);
+ g_idl_node_free ((GIdlNode *)signal->result);
+ }
+ break;
+
+ case G_IDL_NODE_VFUNC:
+ {
+ GIdlNodeVFunc *vfunc = (GIdlNodeVFunc *)node;
+
+ g_free (node->name);
+ for (l = vfunc->parameters; l; l = l->next)
+ g_idl_node_free ((GIdlNode *)l->data);
+ g_list_free (vfunc->parameters);
+ g_idl_node_free ((GIdlNode *)vfunc->result);
+ }
+ break;
+
+ case G_IDL_NODE_FIELD:
+ {
+ GIdlNodeField *field = (GIdlNodeField *)node;
+
+ g_free (node->name);
+ g_idl_node_free ((GIdlNode *)field->type);
+ }
+ break;
+
+ case G_IDL_NODE_OBJECT:
+ case G_IDL_NODE_INTERFACE:
+ {
+ GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
+
+ g_free (node->name);
+ g_free (iface->gtype_name);
+ g_free (iface->gtype_init);
+
+ g_free (iface->parent);
+
+ for (l = iface->interfaces; l; l = l->next)
+ g_free ((GIdlNode *)l->data);
+ g_list_free (iface->interfaces);
+
+ for (l = iface->members; l; l = l->next)
+ g_idl_node_free ((GIdlNode *)l->data);
+ g_list_free (iface->members);
+
+ }
+ break;
+
+ case G_IDL_NODE_VALUE:
+ {
+ GIdlNodeValue *value = (GIdlNodeValue *)node;
+
+ g_free (node->name);
+ }
+ break;
+
+ case G_IDL_NODE_ENUM:
+ case G_IDL_NODE_FLAGS:
+ {
+ GIdlNodeEnum *enum_ = (GIdlNodeEnum *)node;
+
+ g_free (node->name);
+ g_free (enum_->gtype_name);
+ g_free (enum_->gtype_init);
+
+ for (l = enum_->values; l; l = l->next)
+ g_idl_node_free ((GIdlNode *)l->data);
+ g_list_free (enum_->values);
+ }
+ break;
+
+ case G_IDL_NODE_BOXED:
+ {
+ GIdlNodeBoxed *boxed = (GIdlNodeBoxed *)node;
+
+ g_free (node->name);
+ g_free (boxed->gtype_name);
+ g_free (boxed->gtype_init);
+
+ for (l = boxed->members; l; l = l->next)
+ g_idl_node_free ((GIdlNode *)l->data);
+ g_list_free (boxed->members);
+ }
+ break;
+
+ case G_IDL_NODE_STRUCT:
+ {
+ GIdlNodeStruct *struct_ = (GIdlNodeStruct *)node;
+
+ g_free (node->name);
+ for (l = struct_->members; l; l = l->next)
+ g_idl_node_free ((GIdlNode *)l->data);
+ g_list_free (struct_->members);
+ }
+ break;
+
+ case G_IDL_NODE_CONSTANT:
+ {
+ GIdlNodeConstant *constant = (GIdlNodeConstant *)node;
+
+ g_free (node->name);
+ g_free (constant->value);
+ g_idl_node_free ((GIdlNode *)constant->type);
+ }
+ break;
+
+ case G_IDL_NODE_ERROR_DOMAIN:
+ {
+ GIdlNodeErrorDomain *domain = (GIdlNodeErrorDomain *)node;
+
+ g_free (node->name);
+ g_free (domain->getquark);
+ g_free (domain->codes);
+ }
+ break;
+
+ case G_IDL_NODE_XREF:
+ {
+ GIdlNodeXRef *xref = (GIdlNodeXRef *)node;
+
+ g_free (node->name);
+ g_free (xref->namespace);
+ }
+ break;
+
+ case G_IDL_NODE_UNION:
+ {
+ GIdlNodeUnion *union_ = (GIdlNodeUnion *)node;
+
+ g_free (node->name);
+ g_free (union_->gtype_name);
+ g_free (union_->gtype_init);
+
+ g_idl_node_free ((GIdlNode *)union_->discriminator_type);
+ for (l = union_->members; l; l = l->next)
+ g_idl_node_free ((GIdlNode *)l->data);
+ for (l = union_->discriminators; l; l = l->next)
+ g_idl_node_free ((GIdlNode *)l->data);
+ }
+ break;
+
+ default:
+ g_error ("Unhandled node type %d\n", node->type);
+ break;
+ }
+
+ g_free (node);
+}
+
+/* returns the fixed size of the blob */
+guint32
+g_idl_node_get_size (GIdlNode *node)
+{
+ GList *l;
+ gint size, n;
+
+ switch (node->type)
+ {
+ case G_IDL_NODE_CALLBACK:
+ size = 12;
+ break;
+
+ case G_IDL_NODE_FUNCTION:
+ size = 16;
+ break;
+
+ case G_IDL_NODE_PARAM:
+ size = 12;
+ break;
+
+ case G_IDL_NODE_TYPE:
+ size = 4;
+ break;
+
+ case G_IDL_NODE_OBJECT:
+ {
+ GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
+
+ n = g_list_length (iface->interfaces);
+ size = 32 + 2 * (n + (n % 2));
+
+ for (l = iface->members; l; l = l->next)
+ size += g_idl_node_get_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_INTERFACE:
+ {
+ GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
+
+ n = g_list_length (iface->prerequisites);
+ size = 28 + 2 * (n + (n % 2));
+
+ for (l = iface->members; l; l = l->next)
+ size += g_idl_node_get_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_ENUM:
+ case G_IDL_NODE_FLAGS:
+ {
+ GIdlNodeEnum *enum_ = (GIdlNodeEnum *)node;
+
+ size = 20;
+ for (l = enum_->values; l; l = l->next)
+ size += g_idl_node_get_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_VALUE:
+ size = 12;
+ break;
+
+ case G_IDL_NODE_STRUCT:
+ {
+ GIdlNodeStruct *struct_ = (GIdlNodeStruct *)node;
+
+ size = 20;
+ for (l = struct_->members; l; l = l->next)
+ size += g_idl_node_get_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_BOXED:
+ {
+ GIdlNodeBoxed *boxed = (GIdlNodeBoxed *)node;
+
+ size = 20;
+ for (l = boxed->members; l; l = l->next)
+ size += g_idl_node_get_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_PROPERTY:
+ size = 12;
+ break;
+
+ case G_IDL_NODE_SIGNAL:
+ size = 12;
+ break;
+
+ case G_IDL_NODE_VFUNC:
+ size = 16;
+ break;
+
+ case G_IDL_NODE_FIELD:
+ size = 12;
+ break;
+
+ case G_IDL_NODE_CONSTANT:
+ size = 20;
+ break;
+
+ case G_IDL_NODE_ERROR_DOMAIN:
+ size = 16;
+ break;
+
+ case G_IDL_NODE_XREF:
+ size = 0;
+ break;
+
+ case G_IDL_NODE_UNION:
+ {
+ GIdlNodeUnion *union_ = (GIdlNodeUnion *)node;
+
+ size = 28;
+ for (l = union_->members; l; l = l->next)
+ size += g_idl_node_get_size ((GIdlNode *)l->data);
+ for (l = union_->discriminators; l; l = l->next)
+ size += g_idl_node_get_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ default:
+ g_error ("Unhandled node type %d\n", node->type);
+ size = 0;
+ }
+
+ g_debug ("node %d type %d size %d", node, node->type, size);
+
+ return size;
+}
+
+/* returns the full size of the blob including variable-size parts */
+guint32
+g_idl_node_get_full_size (GIdlNode *node)
+{
+ GList *l;
+ gint size, n;
+
+ g_assert (node != NULL);
+
+ switch (node->type)
+ {
+ case G_IDL_NODE_CALLBACK:
+ {
+ GIdlNodeFunction *function = (GIdlNodeFunction *)node;
+ size = 12;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ for (l = function->parameters; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ size += g_idl_node_get_full_size ((GIdlNode *)function->result);
+ }
+ break;
+
+ case G_IDL_NODE_FUNCTION:
+ {
+ GIdlNodeFunction *function = (GIdlNodeFunction *)node;
+ size = 24;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ size += ALIGN_VALUE (strlen (function->symbol) + 1, 4);
+ for (l = function->parameters; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ size += g_idl_node_get_full_size ((GIdlNode *)function->result);
+ }
+ break;
+
+ case G_IDL_NODE_PARAM:
+ {
+ GIdlNodeParam *param = (GIdlNodeParam *)node;
+
+ size = 12;
+ if (node->name)
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ size += g_idl_node_get_full_size ((GIdlNode *)param->type);
+ }
+ break;
+
+ case G_IDL_NODE_TYPE:
+ {
+ GIdlNodeType *type = (GIdlNodeType *)node;
+ if (type->tag < TYPE_TAG_ARRAY)
+ size = 4;
+ else
+ {
+ switch (type->tag)
+ {
+ case TYPE_TAG_ARRAY:
+ size = 4 + 4;
+ if (type->parameter_type1)
+ size += g_idl_node_get_full_size ((GIdlNode *)type->parameter_type1);
+ break;
+ case TYPE_TAG_INTERFACE:
+ size = 4 + 4;
+ break;
+ case TYPE_TAG_LIST:
+ case TYPE_TAG_SLIST:
+ size = 4 + 4;
+ if (type->parameter_type1)
+ size += g_idl_node_get_full_size ((GIdlNode *)type->parameter_type1);
+ break;
+ case TYPE_TAG_HASH:
+ size = 4 + 4 + 4;
+ if (type->parameter_type1)
+ size += g_idl_node_get_full_size ((GIdlNode *)type->parameter_type1);
+ if (type->parameter_type2)
+ size += g_idl_node_get_full_size ((GIdlNode *)type->parameter_type2);
+ break;
+ case TYPE_TAG_ERROR:
+ {
+ gint n;
+
+ if (type->errors)
+ n = g_strv_length (type->errors);
+ else
+ n = 0;
+
+ size = 4 + 4 + 2 * (n + n % 2);
+ }
+ break;
+ default:
+ g_error ("Unknown type tag %d\n", type->tag);
+ break;
+ }
+ }
+ }
+ break;
+
+ case G_IDL_NODE_OBJECT:
+ {
+ GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
+
+ n = g_list_length (iface->interfaces);
+ size = 32;
+ if (iface->parent)
+ size += ALIGN_VALUE (strlen (iface->parent) + 1, 4);
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ size += ALIGN_VALUE (strlen (iface->gtype_name) + 1, 4);
+ size += ALIGN_VALUE (strlen (iface->gtype_init) + 1, 4);
+ size += 2 * (n + (n % 2));
+
+ for (l = iface->members; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_INTERFACE:
+ {
+ GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
+
+ n = g_list_length (iface->prerequisites);
+ size = 28;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ size += ALIGN_VALUE (strlen (iface->gtype_name) + 1, 4);
+ size += ALIGN_VALUE (strlen (iface->gtype_init) + 1, 4);
+ size += 2 * (n + (n % 2));
+
+ for (l = iface->members; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_ENUM:
+ case G_IDL_NODE_FLAGS:
+ {
+ GIdlNodeEnum *enum_ = (GIdlNodeEnum *)node;
+
+ size = 20;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ if (enum_->gtype_name)
+ {
+ size += ALIGN_VALUE (strlen (enum_->gtype_name) + 1, 4);
+ size += ALIGN_VALUE (strlen (enum_->gtype_init) + 1, 4);
+ }
+
+ for (l = enum_->values; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_VALUE:
+ {
+ GIdlNodeValue *value = (GIdlNodeValue *)node;
+
+ size = 12;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ }
+ break;
+
+ case G_IDL_NODE_STRUCT:
+ {
+ GIdlNodeStruct *struct_ = (GIdlNodeStruct *)node;
+
+ size = 20;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ for (l = struct_->members; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_BOXED:
+ {
+ GIdlNodeBoxed *boxed = (GIdlNodeBoxed *)node;
+
+ size = 20;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ if (boxed->gtype_name)
+ {
+ size += ALIGN_VALUE (strlen (boxed->gtype_name) + 1, 4);
+ size += ALIGN_VALUE (strlen (boxed->gtype_init) + 1, 4);
+ }
+ for (l = boxed->members; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_PROPERTY:
+ {
+ GIdlNodeProperty *prop = (GIdlNodeProperty *)node;
+
+ size = 12;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ size += g_idl_node_get_full_size ((GIdlNode *)prop->type);
+ }
+ break;
+
+ case G_IDL_NODE_SIGNAL:
+ {
+ GIdlNodeSignal *signal = (GIdlNodeSignal *)node;
+
+ size = 12;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ for (l = signal->parameters; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ size += g_idl_node_get_full_size ((GIdlNode *)signal->result);
+ }
+ break;
+
+ case G_IDL_NODE_VFUNC:
+ {
+ GIdlNodeVFunc *vfunc = (GIdlNodeVFunc *)node;
+
+ size = 16;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ for (l = vfunc->parameters; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ size += g_idl_node_get_full_size ((GIdlNode *)vfunc->result);
+ }
+ break;
+
+ case G_IDL_NODE_FIELD:
+ {
+ GIdlNodeField *field = (GIdlNodeField *)node;
+
+ size = 12;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ size += g_idl_node_get_full_size ((GIdlNode *)field->type);
+ }
+ break;
+
+ case G_IDL_NODE_CONSTANT:
+ {
+ GIdlNodeConstant *constant = (GIdlNodeConstant *)node;
+
+ size = 20;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ /* FIXME non-string values */
+ size += ALIGN_VALUE (strlen (constant->value) + 1, 4);
+ size += g_idl_node_get_full_size ((GIdlNode *)constant->type);
+ }
+ break;
+
+ case G_IDL_NODE_ERROR_DOMAIN:
+ {
+ GIdlNodeErrorDomain *domain = (GIdlNodeErrorDomain *)node;
+
+ size = 16;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ size += ALIGN_VALUE (strlen (domain->getquark) + 1, 4);
+ }
+ break;
+
+ case G_IDL_NODE_XREF:
+ {
+ GIdlNodeXRef *xref = (GIdlNodeXRef *)node;
+
+ size = 0;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ size += ALIGN_VALUE (strlen (xref->namespace) + 1, 4);
+ }
+ break;
+
+ case G_IDL_NODE_UNION:
+ {
+ GIdlNodeUnion *union_ = (GIdlNodeUnion *)node;
+
+ size = 28;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ for (l = union_->members; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ for (l = union_->discriminators; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ default:
+ g_error ("Unknown type tag %d\n", node->type);
+ size = 0;
+ }
+
+ g_debug ("node %d type %d full size %d", node, node->type, size);
+
+ return size;
+}
+
+static gint64
+parse_int_value (const gchar *str)
+{
+ return strtoll (str, NULL, 0);
+}
+
+static guint64
+parse_uint_value (const gchar *str)
+{
+ return strtoull (str, NULL, 0);
+}
+
+static gdouble
+parse_float_value (const gchar *str)
+{
+ return strtod (str, NULL);
+}
+
+static gboolean
+parse_boolean_value (const gchar *str)
+{
+ if (strcmp (str, "TRUE") == 0)
+ return TRUE;
+
+ if (strcmp (str, "FALSE") == 0)
+ return FALSE;
+
+ return parse_int_value (str) ? TRUE : FALSE;
+}
+
+static GIdlNode *
+find_entry_node (GIdlModule *module,
+ GList *modules,
+ const gchar *name,
+ guint16 *idx)
+
+{
+ GList *l;
+ gint i;
+ gchar **names;
+ gint n_names;
+ GIdlNode *result = NULL;
+
+ names = g_strsplit (name, ".", 0);
+ n_names = g_strv_length (names);
+ if (n_names > 2)
+ g_error ("Too many name parts");
+
+ for (l = module->entries, i = 1; l; l = l->next, i++)
+ {
+ GIdlNode *node = (GIdlNode *)l->data;
+
+ if (n_names > 1)
+ {
+ if (node->type != G_IDL_NODE_XREF)
+ continue;
+
+ if (((GIdlNodeXRef *)node)->namespace == NULL ||
+ strcmp (((GIdlNodeXRef *)node)->namespace, names[0]) != 0)
+ continue;
+ }
+
+ if (strcmp (node->name, names[n_names - 1]) == 0)
+ {
+ if (idx)
+ *idx = i;
+
+ result = node;
+ goto out;
+ }
+ }
+
+ if (n_names > 1)
+ {
+ GIdlNode *node = g_idl_node_new (G_IDL_NODE_XREF);
+
+ ((GIdlNodeXRef *)node)->namespace = g_strdup (names[0]);
+ node->name = g_strdup (names[1]);
+
+ module->entries = g_list_append (module->entries, node);
+
+ if (idx)
+ *idx = g_list_length (module->entries);
+
+ result = node;
+
+ goto out;
+ }
+
+ g_warning ("Entry %s not found", name);
+
+ out:
+
+ g_strfreev (names);
+
+ return result;
+}
+
+static guint16
+find_entry (GIdlModule *module,
+ GList *modules,
+ const gchar *name)
+{
+ guint16 idx = 0;
+
+ find_entry_node (module, modules, name, &idx);
+
+ return idx;
+}
+
+static void
+serialize_type (GIdlModule *module,
+ GList *modules,
+ GIdlNodeType *node,
+ GString *str)
+{
+ gint i;
+ const gchar* basic[] = {
+ "void",
+ "gboolean",
+ "gint8",
+ "guint8",
+ "gint16",
+ "guint16",
+ "gint32",
+ "guint32",
+ "gint64",
+ "guint64",
+ "gint",
+ "guint",
+ "glong",
+ "gulong",
+ "gssize",
+ "gsize",
+ "gfloat",
+ "gdouble",
+ "utf8",
+ "filename"
+ };
+
+ if (node->tag < 20)
+ {
+ g_string_append_printf (str, "%s%s",
+ basic[node->tag], node->is_pointer ? "*" : "");
+ }
+ else if (node->tag == 20)
+ {
+ serialize_type (module, modules, node->parameter_type1, str);
+ g_string_append (str, "[");
+
+ if (node->has_length)
+ g_string_append_printf (str, "length=%d", node->length);
+
+ if (node->zero_terminated)
+ g_string_append_printf (str, "%szero-terminated=1",
+ node->has_length ? "," : "");
+
+ g_string_append (str, "]");
+ }
+ else if (node->tag == 21)
+ {
+ GIdlNode *iface;
+ gchar *name;
+
+ iface = find_entry_node (module, modules, node->interface, NULL);
+ if (iface)
+ name = iface->name;
+ else
+ {
+ g_warning ("Interface for type reference %s not found", node->interface);
+ name = node->interface;
+ }
+
+ g_string_append_printf (str, "%s%s", name, node->is_pointer ? "*" : "");
+ }
+ else if (node->tag == 22)
+ {
+ g_string_append (str, "GList");
+ if (node->parameter_type1)
+ {
+ g_string_append (str, "<");
+ serialize_type (module, modules, node->parameter_type1, str);
+ g_string_append (str, ">");
+ }
+ }
+ else if (node->tag == 23)
+ {
+ g_string_append (str, "GSList");
+ if (node->parameter_type1)
+ {
+ g_string_append (str, "<");
+ serialize_type (module, modules, node->parameter_type1, str);
+ g_string_append (str, ">");
+ }
+ }
+ else if (node->tag == 24)
+ {
+ g_string_append (str, "GHashTable<");
+ if (node->parameter_type1)
+ {
+ g_string_append (str, "<");
+ serialize_type (module, modules, node->parameter_type1, str);
+ g_string_append (str, ",");
+ serialize_type (module, modules, node->parameter_type2, str);
+ g_string_append (str, ">");
+ }
+ }
+ else if (node->tag == 25)
+ {
+ g_string_append (str, "GError");
+ if (node->errors)
+ {
+ g_string_append (str, "<");
+ for (i = 0; node->errors[i]; i++)
+ {
+ if (i > 0)
+ g_string_append (str, ",");
+ g_string_append (str, node->errors[i]);
+ }
+ g_string_append (str, ">");
+ }
+ }
+}
+
+void
+g_idl_node_build_metadata (GIdlNode *node,
+ GIdlModule *module,
+ GList *modules,
+ GHashTable *strings,
+ GHashTable *types,
+ guchar *data,
+ guint32 *offset,
+ guint32 *offset2)
+{
+ GList *l;
+ guint32 old_offset = *offset;
+ guint32 old_offset2 = *offset2;
+
+ switch (node->type)
+ {
+ case G_IDL_NODE_TYPE:
+ {
+ GIdlNodeType *type = (GIdlNodeType *)node;
+ SimpleTypeBlob *blob = (SimpleTypeBlob *)&data[*offset];
+
+ *offset += 4;
+
+ if (type->tag < TYPE_TAG_ARRAY)
+ {
+ blob->reserved = 0;
+ blob->reserved2 = 0;
+ blob->pointer = type->is_pointer;
+ blob->reserved3 = 0;
+ blob->tag = type->tag;
+ }
+ else
+ {
+ GString *str;
+ gchar *s;
+ gpointer value;
+
+ str = g_string_new (0);
+ serialize_type (module, modules, type, str);
+ s = g_string_free (str, FALSE);
+
+ types_count += 1;
+ value = g_hash_table_lookup (types, s);
+ if (value)
+ {
+ blob->offset = GPOINTER_TO_INT (value);
+ g_free (s);
+ }
+ else
+ {
+ unique_types_count += 1;
+ g_hash_table_insert (types, s, GINT_TO_POINTER(*offset2));
+
+ blob->offset = *offset2;
+ switch (type->tag)
+ {
+ case TYPE_TAG_ARRAY:
+ {
+ ArrayTypeBlob *array = (ArrayTypeBlob *)&data[*offset2];
+ guint32 pos;
+
+ array->pointer = 1;
+ array->reserved = 0;
+ array->tag = type->tag;
+ array->zero_terminated = type->zero_terminated;
+ array->has_length = type->has_length;
+ array->reserved2 = 0;
+ array->length = type->length;
+
+ pos = *offset2 + 4;
+ *offset2 += 8;
+
+ g_idl_node_build_metadata ((GIdlNode *)type->parameter_type1,
+ module, modules, strings, types,
+ data, &pos, offset2);
+ }
+ break;
+
+ case TYPE_TAG_INTERFACE:
+ {
+ InterfaceTypeBlob *iface = (InterfaceTypeBlob *)&data[*offset2];
+ *offset2 += 4;
+
+ iface->pointer = type->is_pointer;
+ iface->reserved = 0;
+ iface->tag = type->tag;
+ iface->reserved2 = 0;
+ iface->interface = find_entry (module, modules, type->interface);
+
+ }
+ break;
+
+ case TYPE_TAG_LIST:
+ case TYPE_TAG_SLIST:
+ {
+ ParamTypeBlob *param = (ParamTypeBlob *)&data[*offset2];
+ guint32 pos;
+
+ param->pointer = 1;
+ param->reserved = 0;
+ param->tag = type->tag;
+ param->reserved2 = 0;
+ param->n_types = 1;
+
+ pos = *offset2 + 4;
+ *offset2 += 8;
+
+ g_idl_node_build_metadata ((GIdlNode *)type->parameter_type1,
+ module, modules, strings, types,
+ data, &pos, offset2);
+ }
+ break;
+
+ case TYPE_TAG_HASH:
+ {
+ ParamTypeBlob *param = (ParamTypeBlob *)&data[*offset2];
+ guint32 pos;
+
+ param->pointer = 1;
+ param->reserved = 0;
+ param->tag = type->tag;
+ param->reserved2 = 0;
+ param->n_types = 2;
+
+ pos = *offset2 + 4;
+ *offset2 += 12;
+
+ g_idl_node_build_metadata ((GIdlNode *)type->parameter_type1,
+ module, modules, strings, types,
+ data, &pos, offset2);
+ g_idl_node_build_metadata ((GIdlNode *)type->parameter_type2,
+ module, modules, strings, types,
+ data, &pos, offset2);
+ }
+ break;
+
+ case TYPE_TAG_ERROR:
+ {
+ ErrorTypeBlob *blob = (ErrorTypeBlob *)&data[*offset2];
+ gint i, domain;
+
+ blob->pointer = 1;
+ blob->reserved = 0;
+ blob->tag = type->tag;
+ blob->reserved2 = 0;
+ if (type->errors)
+ blob->n_domains = g_strv_length (type->errors);
+ else
+ blob->n_domains = 0;
+
+ *offset2 = ALIGN_VALUE (*offset2 + 4 + 2 * blob->n_domains, 4);
+ for (i = 0; i < blob->n_domains; i++)
+ blob->domains[i] = find_entry (module, modules, type->errors[i]);
+ }
+ break;
+
+ default:
+ g_error ("Unknown type tag %d\n", type->tag);
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case G_IDL_NODE_FIELD:
+ {
+ GIdlNodeField *field = (GIdlNodeField *)node;
+ FieldBlob *blob;
+
+ blob = (FieldBlob *)&data[*offset];
+ *offset += 8;
+
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->readable = field->readable;
+ blob->writable = field->writable;
+ blob->reserved = 0;
+ blob->bits = 0;
+ blob->struct_offset = field->offset;
+
+ g_idl_node_build_metadata ((GIdlNode *)field->type,
+ module, modules, strings, types,
+ data, offset, offset2);
+ }
+ break;
+
+ case G_IDL_NODE_PROPERTY:
+ {
+ GIdlNodeProperty *prop = (GIdlNodeProperty *)node;
+ PropertyBlob *blob = (PropertyBlob *)&data[*offset];
+ *offset += 8;
+
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->deprecated = prop->deprecated;
+ blob->readable = prop->readable;
+ blob->writable = prop->writable;
+ blob->construct = prop->construct;
+ blob->construct_only = prop->construct_only;
+ blob->reserved = 0;
+
+ g_idl_node_build_metadata ((GIdlNode *)prop->type,
+ module, modules, strings, types,
+ data, offset, offset2);
+ }
+ break;
+
+ case G_IDL_NODE_FUNCTION:
+ {
+ FunctionBlob *blob = (FunctionBlob *)&data[*offset];
+ SignatureBlob *blob2 = (SignatureBlob *)&data[*offset2];
+ GIdlNodeFunction *function = (GIdlNodeFunction *)node;
+ guint32 signature, res;
+ gint n;
+
+ signature = *offset2;
+ n = g_list_length (function->parameters);
+
+ *offset += 16;
+ *offset2 += 8 + n * 12;
+
+ blob->blob_type = BLOB_TYPE_FUNCTION;
+ blob->deprecated = function->deprecated;
+ blob->setter = function->is_setter;
+ blob->getter = function->is_getter;
+ blob->constructor = function->is_constructor;
+ blob->wraps_vfunc = function->wraps_vfunc;
+ blob->reserved = 0;
+ blob->index = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->symbol = write_string (function->symbol, strings, data, offset2);
+ blob->signature = signature;
+
+ g_idl_node_build_metadata ((GIdlNode *)function->result->type,
+ module, modules, strings, types,
+ data, &signature, offset2);
+
+ blob2->may_return_null = function->result->null_ok;
+ blob2->caller_owns_return_value = function->result->transfer;
+ blob2->caller_owns_return_container = function->result->shallow_transfer;
+ blob2->reserved = 0;
+ blob2->n_arguments = n;
+
+ signature += 4;
+
+ for (l = function->parameters; l; l = l->next)
+ {
+ GIdlNode *param = (GIdlNode *)l->data;
+
+ g_idl_node_build_metadata (param,
+ module, modules, strings, types,
+ data, &signature, offset2);
+ }
+ }
+ break;
+
+ case G_IDL_NODE_CALLBACK:
+ {
+ CallbackBlob *blob = (CallbackBlob *)&data[*offset];
+ SignatureBlob *blob2 = (SignatureBlob *)&data[*offset2];
+ GIdlNodeFunction *function = (GIdlNodeFunction *)node;
+ guint32 signature, res;
+ gint n;
+
+ signature = *offset2;
+ n = g_list_length (function->parameters);
+
+ *offset += 12;
+ *offset2 += 8 + n * 12;
+
+ blob->blob_type = BLOB_TYPE_CALLBACK;
+ blob->deprecated = function->deprecated;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->signature = signature;
+
+ g_idl_node_build_metadata ((GIdlNode *)function->result->type,
+ module, modules, strings, types,
+ data, &signature, offset2);
+
+ blob2->may_return_null = function->result->null_ok;
+ blob2->caller_owns_return_value = function->result->transfer;
+ blob2->caller_owns_return_container = function->result->shallow_transfer;
+ blob2->reserved = 0;
+ blob2->n_arguments = n;
+
+ signature += 4;
+
+ for (l = function->parameters; l; l = l->next)
+ {
+ GIdlNode *param = (GIdlNode *)l->data;
+
+ g_idl_node_build_metadata (param,
+ module, modules, strings, types,
+ data, &signature, offset2);
+ }
+ }
+ break;
+
+ case G_IDL_NODE_SIGNAL:
+ {
+ SignalBlob *blob = (SignalBlob *)&data[*offset];
+ SignatureBlob *blob2 = (SignatureBlob *)&data[*offset2];
+ GIdlNodeSignal *signal = (GIdlNodeSignal *)node;
+ guint32 signature, res;
+ gint n;
+
+ signature = *offset2;
+ n = g_list_length (signal->parameters);
+
+ *offset += 12;
+ *offset2 += 8 + n * 12;
+
+ blob->deprecated = signal->deprecated;
+ blob->run_first = signal->run_first;
+ blob->run_last = signal->run_last;
+ blob->run_cleanup = signal->run_cleanup;
+ blob->no_recurse = signal->no_recurse;
+ blob->detailed = signal->detailed;
+ blob->action = signal->action;
+ blob->no_hooks = signal->no_hooks;
+ blob->has_class_closure = 0; /* FIXME */
+ blob->true_stops_emit = 0; /* FIXME */
+ blob->reserved = 0;
+ blob->class_closure = 0; /* FIXME */
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->signature = signature;
+
+ g_idl_node_build_metadata ((GIdlNode *)signal->result->type,
+ module, modules, strings, types,
+ data, &signature, offset2);
+
+ blob2->may_return_null = signal->result->null_ok;
+ blob2->caller_owns_return_value = signal->result->transfer;
+ blob2->caller_owns_return_container = signal->result->shallow_transfer;
+ blob2->reserved = 0;
+ blob2->n_arguments = n;
+
+ signature += 4;
+
+ for (l = signal->parameters; l; l = l->next)
+ {
+ GIdlNode *param = (GIdlNode *)l->data;
+
+ g_idl_node_build_metadata (param, module, modules, strings, types,
+ data, &signature, offset2);
+ }
+ }
+ break;
+
+ case G_IDL_NODE_VFUNC:
+ {
+ VFuncBlob *blob = (VFuncBlob *)&data[*offset];
+ SignatureBlob *blob2 = (SignatureBlob *)&data[*offset2];
+ GIdlNodeVFunc *vfunc = (GIdlNodeVFunc *)node;
+ guint32 signature, res;
+ gint n;
+
+ signature = *offset2;
+ n = g_list_length (vfunc->parameters);
+
+ *offset += 16;
+ *offset2 += 8 + n * 12;
+
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->must_chain_up = 0; /* FIXME */
+ blob->must_be_implemented = 0; /* FIXME */
+ blob->must_not_be_implemented = 0; /* FIXME */
+ blob->class_closure = 0; /* FIXME */
+ blob->reserved = 0;
+
+ blob->struct_offset = vfunc->offset;
+ blob->reserved2 = 0;
+ blob->signature = signature;
+
+ g_idl_node_build_metadata ((GIdlNode *)vfunc->result->type,
+ module, modules, strings, types,
+ data, &signature, offset2);
+
+ blob2->may_return_null = vfunc->result->null_ok;
+ blob2->caller_owns_return_value = vfunc->result->transfer;
+ blob2->caller_owns_return_container = vfunc->result->shallow_transfer;
+ blob2->reserved = 0;
+ blob2->n_arguments = n;
+
+ signature += 4;
+
+ for (l = vfunc->parameters; l; l = l->next)
+ {
+ GIdlNode *param = (GIdlNode *)l->data;
+
+ g_idl_node_build_metadata (param, module, modules, strings,
+ types, data, &signature, offset2);
+ }
+ }
+ break;
+
+ case G_IDL_NODE_PARAM:
+ {
+ ArgBlob *blob = (ArgBlob *)&data[*offset];
+ GIdlNodeParam *param = (GIdlNodeParam *)node;
+ guint32 res;
+
+ *offset += 8;
+
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->in = param->in;
+ blob->out = param->out;
+ blob->dipper = param->dipper;
+ blob->null_ok = param->null_ok;
+ blob->optional = param->optional;
+ blob->transfer_ownership = param->transfer;
+ blob->transfer_container_ownership = param->shallow_transfer;
+ blob->return_value = param->retval;
+ blob->reserved = 0;
+
+ g_idl_node_build_metadata ((GIdlNode *)param->type, module, modules,
+ strings, types, data, offset, offset2);
+ }
+ break;
+
+ case G_IDL_NODE_STRUCT:
+ {
+ StructBlob *blob = (StructBlob *)&data[*offset];
+ GIdlNodeStruct *struct_ = (GIdlNodeStruct *)node;
+ guint32 pos;
+
+ blob->blob_type = BLOB_TYPE_STRUCT;
+ blob->deprecated = struct_->deprecated;
+ blob->unregistered = TRUE;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->gtype_name = 0;
+ blob->gtype_init = 0;
+
+ blob->n_fields = 0;
+ blob->n_methods = 0;
+
+ *offset += 20;
+ for (l = struct_->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_FIELD)
+ {
+ blob->n_fields++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ for (l = struct_->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_FUNCTION)
+ {
+ blob->n_methods++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+ }
+ break;
+
+ case G_IDL_NODE_BOXED:
+ {
+ StructBlob *blob = (StructBlob *)&data[*offset];
+ GIdlNodeBoxed *boxed = (GIdlNodeBoxed *)node;
+
+ blob->blob_type = BLOB_TYPE_BOXED;
+ blob->deprecated = boxed->deprecated;
+ blob->unregistered = FALSE;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->gtype_name = write_string (boxed->gtype_name, strings, data, offset2);
+ blob->gtype_init = write_string (boxed->gtype_init, strings, data, offset2);
+
+ blob->n_fields = 0;
+ blob->n_methods = 0;
+
+ *offset += 20;
+ for (l = boxed->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_FIELD)
+ {
+ blob->n_fields++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ for (l = boxed->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_FUNCTION)
+ {
+ blob->n_methods++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+ }
+ break;
+
+ case G_IDL_NODE_UNION:
+ {
+ UnionBlob *blob = (UnionBlob *)&data[*offset];
+ GIdlNodeUnion *union_ = (GIdlNodeUnion *)node;
+
+ blob->blob_type = BLOB_TYPE_UNION;
+ blob->deprecated = union_->deprecated;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ if (union_->gtype_name)
+ {
+ blob->unregistered = FALSE;
+ blob->gtype_name = write_string (union_->gtype_name, strings, data, offset2);
+ blob->gtype_init = write_string (union_->gtype_init, strings, data, offset2);
+ }
+ else
+ {
+ blob->unregistered = TRUE;
+ blob->gtype_name = 0;
+ blob->gtype_init = 0;
+ }
+
+ blob->n_fields = 0;
+ blob->n_functions = 0;
+
+ blob->discriminator_offset = union_->discriminator_offset;
+
+ if (union_->discriminator_type)
+ {
+ *offset += 24;
+ blob->discriminated = TRUE;
+ g_idl_node_build_metadata ((GIdlNode *)union_->discriminator_type,
+ module, modules, strings, types,
+ data, offset, offset2);
+ }
+ else
+ {
+ *offset += 28;
+ blob->discriminated = FALSE;
+ blob->discriminator_type.offset = 0;
+ }
+
+
+ for (l = union_->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_FIELD)
+ {
+ blob->n_fields++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ for (l = union_->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_FUNCTION)
+ {
+ blob->n_functions++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ if (union_->discriminator_type)
+ {
+ for (l = union_->discriminators; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+ }
+ break;
+
+ case G_IDL_NODE_ENUM:
+ case G_IDL_NODE_FLAGS:
+ {
+ EnumBlob *blob = (EnumBlob *)&data[*offset];
+ GIdlNodeEnum *enum_ = (GIdlNodeEnum *)node;
+
+ *offset += 20;
+
+ if (node->type == G_IDL_NODE_ENUM)
+ blob->blob_type = BLOB_TYPE_ENUM;
+ else
+ blob->blob_type = BLOB_TYPE_FLAGS;
+
+ blob->deprecated = enum_->deprecated;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ if (enum_->gtype_name)
+ {
+ blob->unregistered = FALSE;
+ blob->gtype_name = write_string (enum_->gtype_name, strings, data, offset2);
+ blob->gtype_init = write_string (enum_->gtype_init, strings, data, offset2);
+ }
+ else
+ {
+ blob->unregistered = TRUE;
+ blob->gtype_name = 0;
+ blob->gtype_init = 0;
+ }
+
+ blob->n_values = 0;
+ blob->reserved2 = 0;
+
+ for (l = enum_->values; l; l = l->next)
+ {
+ GIdlNode *value = (GIdlNode *)l->data;
+
+ blob->n_values++;
+ g_idl_node_build_metadata (value, module, modules, strings, types,
+ data, offset, offset2);
+ }
+ }
+ break;
+
+ case G_IDL_NODE_OBJECT:
+ {
+ ObjectBlob *blob = (ObjectBlob *)&data[*offset];
+ GIdlNodeInterface *object = (GIdlNodeInterface *)node;
+ gint parent;
+
+ blob->blob_type = BLOB_TYPE_OBJECT;
+ blob->deprecated = object->deprecated;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->gtype_name = write_string (object->gtype_name, strings, data, offset2);
+ blob->gtype_init = write_string (object->gtype_init, strings, data, offset2);
+ if (object->parent)
+ blob->parent = find_entry (module, modules, object->parent);
+ else
+ blob->parent = 0;
+
+ blob->n_interfaces = 0;
+ blob->n_fields = 0;
+ blob->n_properties = 0;
+ blob->n_methods = 0;
+ blob->n_signals = 0;
+ blob->n_vfuncs = 0;
+ blob->n_constants = 0;
+
+ *offset += 32;
+ for (l = object->interfaces; l; l = l->next)
+ {
+ blob->n_interfaces++;
+ *(guint16*)&data[*offset] = find_entry (module, modules, (gchar *)l->data);
+ *offset += 2;
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_FIELD)
+ {
+ blob->n_fields++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_PROPERTY)
+ {
+ blob->n_properties++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_FUNCTION)
+ {
+ blob->n_methods++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_SIGNAL)
+ {
+ blob->n_signals++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_VFUNC)
+ {
+ blob->n_vfuncs++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_CONSTANT)
+ {
+ blob->n_constants++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+ }
+ break;
+
+ case G_IDL_NODE_INTERFACE:
+ {
+ InterfaceBlob *blob = (InterfaceBlob *)&data[*offset];
+ GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
+
+ blob->blob_type = BLOB_TYPE_INTERFACE;
+ blob->deprecated = iface->deprecated;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->gtype_name = write_string (iface->gtype_name, strings, data, offset2);
+ blob->gtype_init = write_string (iface->gtype_init, strings, data, offset2);
+ blob->n_prerequisites = 0;
+ blob->n_properties = 0;
+ blob->n_methods = 0;
+ blob->n_signals = 0;
+ blob->n_vfuncs = 0;
+ blob->n_constants = 0;
+
+ *offset += 28;
+ for (l = iface->prerequisites; l; l = l->next)
+ {
+ blob->n_prerequisites++;
+ *(guint16*)&data[*offset] = find_entry (module, modules, (gchar *)l->data);
+ *offset += 2;
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = iface->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_PROPERTY)
+ {
+ blob->n_properties++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = iface->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_FUNCTION)
+ {
+ blob->n_methods++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = iface->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_SIGNAL)
+ {
+ blob->n_signals++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = iface->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_VFUNC)
+ {
+ blob->n_vfuncs++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = iface->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_CONSTANT)
+ {
+ blob->n_constants++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+ }
+ break;
+
+
+ case G_IDL_NODE_VALUE:
+ {
+ GIdlNodeValue *value = (GIdlNodeValue *)node;
+ ValueBlob *blob = (ValueBlob *)&data[*offset];
+ *offset += 12;
+
+ blob->deprecated = value->deprecated;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->value = value->value;
+ }
+ break;
+
+ case G_IDL_NODE_ERROR_DOMAIN:
+ {
+ GIdlNodeErrorDomain *domain = (GIdlNodeErrorDomain *)node;
+ ErrorDomainBlob *blob = (ErrorDomainBlob *)&data[*offset];
+ *offset += 16;
+
+ blob->blob_type = BLOB_TYPE_ERROR_DOMAIN;
+ blob->deprecated = domain->deprecated;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->get_quark = write_string (domain->getquark, strings, data, offset2);
+ blob->error_codes = find_entry (module, modules, domain->codes);
+ blob->reserved2 = 0;
+ }
+ break;
+
+ case G_IDL_NODE_CONSTANT:
+ {
+ GIdlNodeConstant *constant = (GIdlNodeConstant *)node;
+ ConstantBlob *blob = (ConstantBlob *)&data[*offset];
+ guint32 pos;
+
+ pos = *offset + 8;
+ *offset += 20;
+
+ blob->blob_type = BLOB_TYPE_CONSTANT;
+ blob->deprecated = constant->deprecated;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+
+ blob->offset = *offset2;
+ switch (constant->type->tag)
+ {
+ case TYPE_TAG_BOOLEAN:
+ blob->size = 4;
+ *(gboolean*)&data[blob->offset] = parse_boolean_value (constant->value);
+ break;
+ case TYPE_TAG_INT8:
+ blob->size = 1;
+ *(gint8*)&data[blob->offset] = (gint8) parse_int_value (constant->value);
+ break;
+ case TYPE_TAG_UINT8:
+ blob->size = 1;
+ *(guint8*)&data[blob->offset] = (guint8) parse_uint_value (constant->value);
+ break;
+ case TYPE_TAG_INT16:
+ blob->size = 2;
+ *(gint16*)&data[blob->offset] = (gint16) parse_int_value (constant->value);
+ break;
+ case TYPE_TAG_UINT16:
+ blob->size = 2;
+ *(guint16*)&data[blob->offset] = (guint16) parse_uint_value (constant->value);
+ break;
+ case TYPE_TAG_INT32:
+ blob->size = 4;
+ *(gint32*)&data[blob->offset] = (gint32) parse_int_value (constant->value);
+ break;
+ case TYPE_TAG_UINT32:
+ blob->size = 4;
+ *(guint32*)&data[blob->offset] = (guint32) parse_uint_value (constant->value);
+ break;
+ case TYPE_TAG_INT64:
+ blob->size = 8;
+ *(gint64*)&data[blob->offset] = (gint64) parse_int_value (constant->value);
+ break;
+ case TYPE_TAG_UINT64:
+ blob->size = 8;
+ *(guint64*)&data[blob->offset] = (guint64) parse_uint_value (constant->value);
+ break;
+ case TYPE_TAG_INT:
+ blob->size = sizeof (gint);
+ *(gint*)&data[blob->offset] = (gint) parse_int_value (constant->value);
+ break;
+ case TYPE_TAG_UINT:
+ blob->size = sizeof (guint);
+ *(gint*)&data[blob->offset] = (guint) parse_uint_value (constant->value);
+ break;
+ case TYPE_TAG_SSIZE: /* FIXME */
+ case TYPE_TAG_LONG:
+ blob->size = sizeof (glong);
+ *(glong*)&data[blob->offset] = (glong) parse_int_value (constant->value);
+ break;
+ case TYPE_TAG_SIZE: /* FIXME */
+ case TYPE_TAG_ULONG:
+ blob->size = sizeof (gulong);
+ *(gulong*)&data[blob->offset] = (gulong) parse_uint_value (constant->value);
+ break;
+ case TYPE_TAG_FLOAT:
+ blob->size = sizeof (gfloat);
+ *(gfloat*)&data[blob->offset] = (gfloat) parse_float_value (constant->value);
+ break;
+ case TYPE_TAG_DOUBLE:
+ blob->size = sizeof (gdouble);
+ *(gdouble*)&data[blob->offset] = (gdouble) parse_float_value (constant->value);
+ break;
+ case TYPE_TAG_UTF8:
+ case TYPE_TAG_FILENAME:
+ blob->size = strlen (constant->value) + 1;
+ memcpy (&data[blob->offset], constant->value, blob->size);
+ break;
+ }
+ *offset2 += ALIGN_VALUE (blob->size, 4);
+
+ g_idl_node_build_metadata ((GIdlNode *)constant->type, module, modules,
+ strings, types, data, &pos, offset2);
+ }
+ break;
+ }
+
+ g_debug ("node %p type %d, offset %d -> %d, offset2 %d -> %d",
+ node, node->type, old_offset, *offset, old_offset2, *offset2);
+
+ if (*offset2 - old_offset2 + *offset - old_offset > g_idl_node_get_full_size (node))
+ g_error ("exceeding space reservation !!");
+}
+
+/* if str is already in the pool, return previous location, otherwise write str
+ * to the metadata at offset, put it in the pool and update offset. If the
+ * metadata is not large enough to hold the string, reallocate it.
+ */
+guint32
+write_string (const gchar *str,
+ GHashTable *strings,
+ guchar *data,
+ guint32 *offset)
+{
+ gpointer value;
+ guint32 start;
+
+ string_count += 1;
+ string_size += strlen (str);
+
+ value = g_hash_table_lookup (strings, str);
+
+ if (value)
+ return GPOINTER_TO_INT (value);
+
+ unique_string_count += 1;
+ unique_string_size += strlen (str);
+
+ g_hash_table_insert (strings, (gpointer)str, GINT_TO_POINTER (*offset));
+
+ start = *offset;
+ *offset = ALIGN_VALUE (start + strlen (str) + 1, 4);
+
+ strcpy ((gchar*)&data[start], str);
+
+ return start;
+}
+
diff --git a/gobject-introspection/gidlnode.h b/gobject-introspection/gidlnode.h
new file mode 100644
index 000000000..7b6f1568c
--- /dev/null
+++ b/gobject-introspection/gidlnode.h
@@ -0,0 +1,331 @@
+/* GObject introspection: Parsed IDL
+ *
+ * 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.
+ */
+
+#ifndef __G_IDL_NODE_H__
+#define __G_IDL_NODE_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GIdlNode GIdlNode;
+typedef struct _GIdlNodeFunction GIdlNodeFunction;
+typedef struct _GIdlNodeParam GIdlNodeParam;
+typedef struct _GIdlNodeType GIdlNodeType;
+typedef struct _GIdlNodeInterface GIdlNodeInterface;
+typedef struct _GIdlNodeSignal GIdlNodeSignal;
+typedef struct _GIdlNodeProperty GIdlNodeProperty;
+typedef struct _GIdlNodeVFunc GIdlNodeVFunc;
+typedef struct _GIdlNodeField GIdlNodeField;
+typedef struct _GIdlNodeValue GIdlNodeValue;
+typedef struct _GIdlNodeEnum GIdlNodeEnum;
+typedef struct _GIdlNodeBoxed GIdlNodeBoxed;
+typedef struct _GIdlNodeStruct GIdlNodeStruct;
+typedef struct _GIdlNodeConstant GIdlNodeConstant;
+typedef struct _GIdlNodeErrorDomain GIdlNodeErrorDomain;
+typedef struct _GIdlNodeXRef GIdlNodeXRef;
+typedef struct _GIdlNodeUnion GIdlNodeUnion;
+
+typedef enum
+{
+ G_IDL_NODE_INVALID,
+ G_IDL_NODE_FUNCTION,
+ G_IDL_NODE_CALLBACK,
+ G_IDL_NODE_STRUCT,
+ G_IDL_NODE_BOXED,
+ G_IDL_NODE_ENUM,
+ G_IDL_NODE_FLAGS,
+ G_IDL_NODE_OBJECT,
+ G_IDL_NODE_INTERFACE,
+ G_IDL_NODE_CONSTANT,
+ G_IDL_NODE_ERROR_DOMAIN,
+ G_IDL_NODE_UNION,
+ G_IDL_NODE_PARAM,
+ G_IDL_NODE_TYPE,
+ G_IDL_NODE_PROPERTY,
+ G_IDL_NODE_SIGNAL,
+ G_IDL_NODE_VALUE,
+ G_IDL_NODE_VFUNC,
+ G_IDL_NODE_FIELD,
+ G_IDL_NODE_XREF
+} GIdlNodeTypeId;
+
+struct _GIdlNode
+{
+ GIdlNodeTypeId type;
+ gchar *name;
+};
+
+struct _GIdlNodeXRef
+{
+ GIdlNode node;
+
+ gchar *namespace;
+};
+
+struct _GIdlNodeFunction
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ gboolean is_method;
+ gboolean is_setter;
+ gboolean is_getter;
+ gboolean is_constructor;
+ gboolean wraps_vfunc;
+
+ gchar *symbol;
+
+ GIdlNodeParam *result;
+ GList *parameters;
+};
+
+struct _GIdlNodeType
+{
+ GIdlNode node;
+
+ gboolean is_pointer;
+ gboolean is_basic;
+ gboolean is_array;
+ gboolean is_glist;
+ gboolean is_gslist;
+ gboolean is_ghashtable;
+ gboolean is_interface;
+ gboolean is_error;
+ gint tag;
+
+ gchar *unparsed;
+
+ gboolean zero_terminated;
+ gboolean has_length;
+ gint length;
+
+ GIdlNodeType *parameter_type1;
+ GIdlNodeType *parameter_type2;
+
+ gchar *interface;
+ gchar **errors;
+};
+
+struct _GIdlNodeParam
+{
+ GIdlNode node;
+
+ gboolean in;
+ gboolean out;
+ gboolean dipper;
+ gboolean optional;
+ gboolean retval;
+ gboolean null_ok;
+ gboolean transfer;
+ gboolean shallow_transfer;
+
+ GIdlNodeType *type;
+};
+
+struct _GIdlNodeProperty
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ gchar *name;
+ gboolean readable;
+ gboolean writable;
+ gboolean construct;
+ gboolean construct_only;
+
+ GIdlNodeType *type;
+};
+
+struct _GIdlNodeSignal
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ gboolean run_first;
+ gboolean run_last;
+ gboolean run_cleanup;
+ gboolean no_recurse;
+ gboolean detailed;
+ gboolean action;
+ gboolean no_hooks;
+
+ gboolean has_class_closure;
+ gboolean true_stops_emit;
+
+ gint class_closure;
+
+ GList *parameters;
+ GIdlNodeParam *result;
+};
+
+struct _GIdlNodeVFunc
+{
+ GIdlNode node;
+
+ gboolean must_chain_up;
+ gboolean must_be_implemented;
+ gboolean must_not_be_implemented;
+ gboolean is_class_closure;
+
+ GList *parameters;
+ GIdlNodeParam *result;
+
+ gint offset;
+};
+
+struct _GIdlNodeField
+{
+ GIdlNode node;
+
+ gboolean readable;
+ gboolean writable;
+ gint bits;
+ gint offset;
+
+ GIdlNodeType *type;
+};
+
+struct _GIdlNodeInterface
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ gchar *gtype_name;
+ gchar *gtype_init;
+
+ gchar *parent;
+
+ GList *interfaces;
+ GList *prerequisites;
+
+ GList *members;
+};
+
+struct _GIdlNodeValue
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ guint32 value;
+};
+
+struct _GIdlNodeConstant
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ GIdlNodeType *type;
+
+ gchar *value;
+};
+
+struct _GIdlNodeEnum
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ gchar *gtype_name;
+ gchar *gtype_init;
+
+ GList *values;
+};
+
+struct _GIdlNodeBoxed
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ gchar *gtype_name;
+ gchar *gtype_init;
+
+ GList *members;
+};
+
+struct _GIdlNodeStruct
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ GList *members;
+};
+
+struct _GIdlNodeUnion
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ GList *members;
+ GList *discriminators;
+
+ gchar *gtype_name;
+ gchar *gtype_init;
+
+ gint discriminator_offset;
+ GIdlNodeType *discriminator_type;
+};
+
+
+struct _GIdlNodeErrorDomain
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ gchar *name;
+ gchar *getquark;
+ gchar *codes;
+};
+
+
+GIdlNode *g_idl_node_new (GIdlNodeTypeId type);
+void g_idl_node_free (GIdlNode *node);
+guint32 g_idl_node_get_size (GIdlNode *node);
+guint32 g_idl_node_get_full_size (GIdlNode *node);
+void g_idl_node_build_metadata (GIdlNode *node,
+ GIdlModule *module,
+ GList *modules,
+ GHashTable *strings,
+ GHashTable *types,
+ guchar *data,
+ guint32 *offset,
+ guint32 *offset2);
+
+guint32 write_string (const gchar *str,
+ GHashTable *strings,
+ guchar *data,
+ guint32 *offset);
+
+void init_stats (void);
+void dump_stats (void);
+
+G_END_DECLS
+
+#endif /* __G_IDL_NODE_H__ */
diff --git a/gobject-introspection/gidlparser.c b/gobject-introspection/gidlparser.c
new file mode 100644
index 000000000..b774bb984
--- /dev/null
+++ b/gobject-introspection/gidlparser.c
@@ -0,0 +1,2036 @@
+/* GObject introspection: A parser for the XML IDL format
+ *
+ * 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 <string.h>
+
+#include <glib.h>
+#include "gidlmodule.h"
+#include "gidlnode.h"
+#include "gmetadata.h"
+
+typedef enum
+{
+ STATE_START,
+ STATE_END,
+ STATE_ROOT,
+ STATE_NAMESPACE,
+ STATE_FUNCTION,
+ STATE_PARAMETERS,
+ STATE_OBJECT,
+ STATE_INTERFACE,
+ STATE_IMPLEMENTS,
+ STATE_REQUIRES,
+ STATE_ENUM,
+ STATE_BOXED,
+ STATE_STRUCT,
+ STATE_SIGNAL,
+ STATE_ERRORDOMAIN,
+ STATE_UNION
+} ParseState;
+
+typedef struct _ParseContext ParseContext;
+struct _ParseContext
+{
+ ParseState state;
+ ParseState prev_state;
+
+ GList *modules;
+
+ GIdlModule *current_module;
+ GIdlNode *current_node;
+};
+
+#define MISSING_ATTRIBUTE(error,element,attribute) \
+ g_set_error (error, \
+ G_MARKUP_ERROR, \
+ G_MARKUP_ERROR_INVALID_CONTENT, \
+ "The attribute '%s' on the element '%s' must be specified", \
+ attribute, element)
+
+static const gchar *
+find_attribute (const gchar *name,
+ const gchar **attribute_names,
+ const gchar **attribute_values)
+{
+ gint i;
+
+ for (i = 0; attribute_names[i] != NULL; i++)
+ if (strcmp (attribute_names[i], name) == 0)
+ return attribute_values[i];
+
+ return 0;
+}
+
+static GIdlNodeType *
+parse_type_internal (gchar *str, gchar **rest)
+{
+ gint i;
+
+ static struct {
+ const gchar *str;
+ gint tag;
+ gboolean pointer;
+ } basic[] = {
+ { "void", TYPE_TAG_VOID, 0 },
+ { "gpointer", TYPE_TAG_VOID, 1 },
+ { "gboolean", TYPE_TAG_BOOLEAN, 0 },
+ { "int8_t", TYPE_TAG_INT8, 0 },
+ { "int8", TYPE_TAG_INT8, 0 },
+ { "gint8", TYPE_TAG_INT8, 0 },
+ { "uint8_t", TYPE_TAG_UINT8, 0 },
+ { "uint8", TYPE_TAG_UINT8, 0 },
+ { "guint8", TYPE_TAG_UINT8, 0 },
+ { "int16_t", TYPE_TAG_INT16, 0 },
+ { "int16", TYPE_TAG_INT16, 0 },
+ { "gint16", TYPE_TAG_INT16, 0 },
+ { "uint16_t", TYPE_TAG_UINT16, 0 },
+ { "uint16", TYPE_TAG_UINT16, 0 },
+ { "guint16", TYPE_TAG_UINT16, 0 },
+ { "int32_t", TYPE_TAG_INT32, 0 },
+ { "int32", TYPE_TAG_INT32, 0 },
+ { "gint32", TYPE_TAG_INT32, 0 },
+ { "uint32_t", TYPE_TAG_UINT32, 0 },
+ { "uint32", TYPE_TAG_UINT32, 0 },
+ { "guint32", TYPE_TAG_UINT32, 0 },
+ { "int64_t", TYPE_TAG_INT64, 0 },
+ { "int64", TYPE_TAG_INT64, 0 },
+ { "gint64", TYPE_TAG_INT64, 0 },
+ { "uint64_t", TYPE_TAG_UINT64, 0 },
+ { "uint64", TYPE_TAG_UINT64, 0 },
+ { "guint64", TYPE_TAG_UINT64, 0 },
+ { "int", TYPE_TAG_INT, 0 },
+ { "gint", TYPE_TAG_INT, 0 },
+ { "uint", TYPE_TAG_UINT, 0 },
+ { "guint", TYPE_TAG_UINT, 0 },
+ { "long", TYPE_TAG_LONG, 0 },
+ { "glong", TYPE_TAG_LONG, 0 },
+ { "ulong", TYPE_TAG_ULONG, 0 },
+ { "gulong", TYPE_TAG_ULONG, 0 },
+ { "ssize_t", TYPE_TAG_SSIZE, 0 },
+ { "gssize", TYPE_TAG_SSIZE, 0 },
+ { "size_t", TYPE_TAG_SIZE, 0 },
+ { "gsize", TYPE_TAG_SIZE, 0 },
+ { "float", TYPE_TAG_FLOAT, 0 },
+ { "gfloat", TYPE_TAG_FLOAT, 0 },
+ { "double", TYPE_TAG_DOUBLE, 0 },
+ { "gdouble", TYPE_TAG_DOUBLE, 0 },
+ { "utf8", TYPE_TAG_UTF8, 1 },
+ { "gchar*", TYPE_TAG_UTF8, 1 },
+ { "filename", TYPE_TAG_FILENAME,1 }
+ };
+
+ gint n_basic = G_N_ELEMENTS (basic);
+ gchar *start, *end;
+
+ GIdlNodeType *type;
+
+ type = (GIdlNodeType *)g_idl_node_new (G_IDL_NODE_TYPE);
+
+ str = g_strstrip (str);
+
+ type->unparsed = g_strdup (str);
+
+ *rest = str;
+ for (i = 0; i < n_basic; i++)
+ {
+ if (g_str_has_prefix (*rest, basic[i].str))
+ {
+ type->is_basic = TRUE;
+ type->tag = basic[i].tag;
+ type->is_pointer = basic[i].pointer;
+
+ *rest += strlen(basic[i].str);
+ *rest = g_strchug (*rest);
+ if (**rest == '*' && !type->is_pointer)
+ {
+ type->is_pointer = TRUE;
+ (*rest)++;
+ }
+
+ break;
+ }
+ }
+
+ if (i < n_basic)
+ /* found a basic type */;
+ else if (g_str_has_prefix (*rest, "GList") ||
+ g_str_has_prefix (*rest, "GSList"))
+ {
+ if (g_str_has_prefix (*rest, "GList"))
+ {
+ type->tag = TYPE_TAG_LIST;
+ type->is_glist = TRUE;
+ type->is_pointer = TRUE;
+ *rest += strlen ("GList");
+ }
+ else
+ {
+ type->tag = TYPE_TAG_SLIST;
+ type->is_gslist = TRUE;
+ type->is_pointer = TRUE;
+ *rest += strlen ("GSList");
+ }
+
+ *rest = g_strchug (*rest);
+
+ if (**rest == '<')
+ {
+ (*rest)++;
+
+ type->parameter_type1 = parse_type_internal (*rest, rest);
+ if (type->parameter_type1 == NULL)
+ goto error;
+
+ *rest = g_strchug (*rest);
+
+ if ((*rest)[0] != '>')
+ goto error;
+ (*rest)++;
+ }
+ }
+ else if (g_str_has_prefix (*rest, "GHashTable"))
+ {
+ type->tag = TYPE_TAG_HASH;
+ type->is_ghashtable = TRUE;
+ type->is_pointer = TRUE;
+ *rest += strlen ("GHashTable");
+
+ *rest = g_strchug (*rest);
+
+ if (**rest == '<')
+ {
+ (*rest)++;
+
+ type->parameter_type1 = parse_type_internal (*rest, rest);
+ if (type->parameter_type1 == NULL)
+ goto error;
+
+ *rest = g_strchug (*rest);
+
+ if ((*rest)[0] != ',')
+ goto error;
+ (*rest)++;
+
+ type->parameter_type2 = parse_type_internal (*rest, rest);
+ if (type->parameter_type2 == NULL)
+ goto error;
+
+ if ((*rest)[0] != '>')
+ goto error;
+ (*rest)++;
+ }
+ }
+ else if (g_str_has_prefix (*rest, "GError"))
+ {
+ type->tag = TYPE_TAG_ERROR;
+ type->is_error = TRUE;
+ type->is_pointer = TRUE;
+ *rest += strlen ("GError");
+
+ *rest = g_strchug (*rest);
+
+ if (**rest == '<')
+ {
+ (*rest)++;
+
+ end = strchr (*rest, '>');
+ str = g_strndup (*rest, end - *rest);
+ type->errors = g_strsplit (str, ",", 0);
+ g_free (str);
+
+ *rest = end + 1;
+ }
+ }
+ else
+ {
+ type->tag = TYPE_TAG_INTERFACE;
+ type->is_interface = TRUE;
+ start = *rest;
+
+ /* must be an interface type */
+ while (g_ascii_isalnum (**rest) ||
+ **rest == '.' ||
+ **rest == '-' ||
+ **rest == '_' ||
+ **rest == ':')
+ (*rest)++;
+
+ type->interface = g_strndup (start, *rest - start);
+
+ *rest = g_strchug (*rest);
+ if (**rest == '*')
+ {
+ type->is_pointer = TRUE;
+ (*rest)++;
+ }
+ }
+
+ *rest = g_strchug (*rest);
+ if (g_str_has_prefix (*rest, "["))
+ {
+ GIdlNodeType *array;
+
+ array = (GIdlNodeType *)g_idl_node_new (G_IDL_NODE_TYPE);
+
+ array->tag = TYPE_TAG_ARRAY;
+ array->is_pointer = TRUE;
+ array->is_array = TRUE;
+
+ array->parameter_type1 = type;
+
+ array->zero_terminated = FALSE;
+ array->has_length = FALSE;
+ array->length = 0;
+
+ if (!g_str_has_prefix (*rest, "[]"))
+ {
+ gchar *end, *str, **opts;
+
+ end = strchr (*rest, ']');
+ str = g_strndup (*rest + 1, (end - *rest) - 1);
+ opts = g_strsplit (str, ",", 0);
+
+ *rest = end + 1;
+
+ for (i = 0; opts[i]; i++)
+ {
+ gchar **vals;
+
+ vals = g_strsplit (opts[i], "=", 0);
+
+ if (strcmp (vals[0], "zero-terminated") == 0)
+ array->zero_terminated = (strcmp (vals[1], "1") == 0);
+ else if (strcmp (vals[0], "length") == 0)
+ {
+ array->has_length = TRUE;
+ array->length = atoi (vals[1]);
+ }
+
+ g_strfreev (vals);
+ }
+
+ g_free (str);
+ g_strfreev (opts);
+ }
+
+ type = array;
+ }
+
+ return type;
+
+ error:
+ g_idl_node_free ((GIdlNode *)type);
+
+ return NULL;
+}
+
+static GIdlNodeType *
+parse_type (const gchar *type)
+{
+ gchar *str;
+ gchar *rest;
+ GIdlNodeType *node;
+
+ str = g_strdup (type);
+ node = parse_type_internal (str, &rest);
+ g_free (str);
+
+ return node;
+}
+
+static gboolean
+start_boxed (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "boxed") == 0 &&
+ ctx->state == STATE_NAMESPACE)
+ {
+ const gchar *name;
+ const gchar *typename;
+ const gchar *typeinit;
+ const gchar *deprecated;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ typename = find_attribute ("type-name", attribute_names, attribute_values);
+ typeinit = find_attribute ("get-type", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (typename == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "type-name");
+ else if (typeinit == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "get-type");
+ else
+ {
+ GIdlNodeBoxed *boxed;
+
+ boxed = (GIdlNodeBoxed *) g_idl_node_new (G_IDL_NODE_BOXED);
+
+ ((GIdlNode *)boxed)->name = g_strdup (name);
+ boxed->gtype_name = g_strdup (typename);
+ boxed->gtype_init = g_strdup (typeinit);
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ boxed->deprecated = TRUE;
+ else
+ boxed->deprecated = FALSE;
+
+ ctx->current_node = (GIdlNode *)boxed;
+ ctx->current_module->entries =
+ g_list_append (ctx->current_module->entries, boxed);
+
+ ctx->state = STATE_BOXED;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+start_function (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if ((ctx->state == STATE_NAMESPACE &&
+ (strcmp (element_name, "function") == 0 ||
+ strcmp (element_name, "callback") == 0)) ||
+ ((ctx->state == STATE_OBJECT ||
+ ctx->state == STATE_INTERFACE ||
+ ctx->state == STATE_BOXED ||
+ ctx->state == STATE_STRUCT ||
+ ctx->state == STATE_UNION) &&
+ strcmp (element_name, "method") == 0) ||
+ ((ctx->state == STATE_OBJECT ||
+ ctx->state == STATE_BOXED) &&
+ strcmp (element_name, "constructor") == 0))
+ {
+ const gchar *name;
+ const gchar *symbol;
+ const gchar *deprecated;
+ const gchar *type;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ symbol = find_attribute ("symbol", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+ type = find_attribute ("type", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "symbol");
+ else
+ {
+ GIdlNodeFunction *function;
+
+ function = (GIdlNodeFunction *) g_idl_node_new (G_IDL_NODE_FUNCTION);
+
+ ((GIdlNode *)function)->name = g_strdup (name);
+ function->symbol = g_strdup (symbol);
+ function->parameters = NULL;
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ function->deprecated = TRUE;
+ else
+ function->deprecated = FALSE;
+
+ if (strcmp (element_name, "method") == 0 ||
+ strcmp (element_name, "constructor") == 0)
+ {
+ function->is_method = TRUE;
+
+ if (type && strcmp (type, "setter") == 0)
+ function->is_setter = TRUE;
+ else if (type && strcmp (type, "getter") == 0)
+ function->is_getter = TRUE;
+
+ if (strcmp (element_name, "constructor") == 0)
+ function->is_constructor = TRUE;
+ else
+ function->is_constructor = FALSE;
+ }
+ else
+ {
+ function->is_method = FALSE;
+ function->is_setter = FALSE;
+ function->is_getter = FALSE;
+ function->is_constructor = FALSE;
+ if (strcmp (element_name, "callback") == 0)
+ ((GIdlNode *)function)->type = G_IDL_NODE_CALLBACK;
+ }
+
+ if (ctx->current_node == NULL)
+ {
+ ctx->current_module->entries =
+ g_list_append (ctx->current_module->entries, function);
+ }
+ else
+ switch (ctx->current_node->type)
+ {
+ case G_IDL_NODE_INTERFACE:
+ case G_IDL_NODE_OBJECT:
+ {
+ GIdlNodeInterface *iface;
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface->members = g_list_append (iface->members, function);
+ }
+ break;
+ case G_IDL_NODE_BOXED:
+ {
+ GIdlNodeBoxed *boxed;
+
+ boxed = (GIdlNodeBoxed *)ctx->current_node;
+ boxed->members = g_list_append (boxed->members, function);
+ }
+ break;
+ case G_IDL_NODE_STRUCT:
+ {
+ GIdlNodeStruct *struct_;
+
+ struct_ = (GIdlNodeStruct *)ctx->current_node;
+ struct_->members = g_list_append (struct_->members, function); }
+ break;
+ case G_IDL_NODE_UNION:
+ {
+ GIdlNodeUnion *union_;
+
+ union_ = (GIdlNodeUnion *)ctx->current_node;
+ union_->members = g_list_append (union_->members, function);
+ }
+ break;
+ }
+
+ ctx->current_node = (GIdlNode *)function;
+ ctx->state = STATE_FUNCTION;
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean
+start_parameter (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "parameter") == 0 &&
+ ctx->state == STATE_PARAMETERS)
+ {
+ const gchar *type;
+ const gchar *name;
+ const gchar *direction;
+ const gchar *retval;
+ const gchar *dipper;
+ const gchar *optional;
+ const gchar *nullok;
+ const gchar *transfer;
+
+ type = find_attribute ("type", attribute_names, attribute_values);
+ name = find_attribute ("name", attribute_names, attribute_values);
+ direction = find_attribute ("direction", attribute_names, attribute_values);
+ retval = find_attribute ("retval", attribute_names, attribute_values);
+ dipper = find_attribute ("dipper", attribute_names, attribute_values);
+ optional = find_attribute ("optional", attribute_names, attribute_values);
+ nullok = find_attribute ("null-ok", attribute_names, attribute_values);
+ transfer = find_attribute ("transfer", attribute_names, attribute_values);
+
+ if (type == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "type");
+ else if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else
+ {
+ GIdlNodeParam *param;
+
+ param = (GIdlNodeParam *)g_idl_node_new (G_IDL_NODE_PARAM);
+
+ if (direction && strcmp (direction, "out") == 0)
+ {
+ param->in = FALSE;
+ param->out = TRUE;
+ }
+ else if (direction && strcmp (direction, "inout") == 0)
+ {
+ param->in = TRUE;
+ param->out = TRUE;
+ }
+ else
+ {
+ param->in = TRUE;
+ param->out = FALSE;
+ }
+
+ if (retval && strcmp (retval, "1") == 0)
+ param->retval = TRUE;
+ else
+ param->retval = FALSE;
+
+ if (dipper && strcmp (dipper, "1") == 0)
+ param->dipper = TRUE;
+ else
+ param->dipper = FALSE;
+
+ if (optional && strcmp (optional, "1") == 0)
+ param->optional = TRUE;
+ else
+ param->optional = FALSE;
+
+ if (nullok && strcmp (nullok, "1") == 0)
+ param->null_ok = TRUE;
+ else
+ param->null_ok = FALSE;
+
+ if (transfer && strcmp (transfer, "none") == 0)
+ {
+ param->transfer = FALSE;
+ param->shallow_transfer = FALSE;
+ }
+ else if (transfer && strcmp (transfer, "shallow") == 0)
+ {
+ param->transfer = FALSE;
+ param->shallow_transfer = TRUE;
+ }
+ else
+ {
+ param->transfer = TRUE;
+ param->shallow_transfer = FALSE;
+ }
+
+ ((GIdlNode *)param)->name = g_strdup (name);
+ param->type = parse_type (type);
+
+ switch (ctx->current_node->type)
+ {
+ case G_IDL_NODE_FUNCTION:
+ case G_IDL_NODE_CALLBACK:
+ {
+ GIdlNodeFunction *func;
+
+ func = (GIdlNodeFunction *)ctx->current_node;
+ func->parameters = g_list_append (func->parameters, param);
+ }
+ break;
+ case G_IDL_NODE_SIGNAL:
+ {
+ GIdlNodeSignal *signal;
+
+ signal = (GIdlNodeSignal *)ctx->current_node;
+ signal->parameters = g_list_append (signal->parameters, param);
+ }
+ break;
+ case G_IDL_NODE_VFUNC:
+ {
+ GIdlNodeVFunc *vfunc;
+
+ vfunc = (GIdlNodeVFunc *)ctx->current_node;
+ vfunc->parameters = g_list_append (vfunc->parameters, param);
+ }
+ break;
+ }
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+start_field (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "field") == 0 &&
+ (ctx->state == STATE_OBJECT ||
+ ctx->state == STATE_BOXED ||
+ ctx->state == STATE_STRUCT ||
+ ctx->state == STATE_UNION))
+ {
+ const gchar *name;
+ const gchar *type;
+ const gchar *readable;
+ const gchar *writable;
+ const gchar *bits;
+ const gchar *branch;
+ const gchar *offset;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ type = find_attribute ("type", attribute_names, attribute_values);
+ readable = find_attribute ("readable", attribute_names, attribute_values);
+ writable = find_attribute ("writable", attribute_names, attribute_values);
+ bits = find_attribute ("bits", attribute_names, attribute_values);
+ branch = find_attribute ("branch", attribute_names, attribute_values);
+ offset = find_attribute ("offset", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (type == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "type");
+ else
+ {
+ GIdlNodeField *field;
+
+ field = (GIdlNodeField *)g_idl_node_new (G_IDL_NODE_FIELD);
+ ((GIdlNode *)field)->name = g_strdup (name);
+ if (readable && strcmp (readable, "1") == 0)
+ field->readable = TRUE;
+ else
+ field->readable = FALSE;
+
+ if (writable && strcmp (writable, "1") == 0)
+ field->writable = TRUE;
+ else
+ field->writable = FALSE;
+
+ if (bits)
+ field->bits = atoi (bits);
+ else
+ field->bits = 0;
+
+ if (offset)
+ field->offset = atoi (offset);
+ else
+ field->offset = 0;
+
+ field->type = parse_type (type);
+
+ switch (ctx->current_node->type)
+ {
+ case G_IDL_NODE_OBJECT:
+ {
+ GIdlNodeInterface *iface;
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface->members = g_list_append (iface->members, field);
+ }
+ break;
+ case G_IDL_NODE_BOXED:
+ {
+ GIdlNodeBoxed *boxed;
+
+ boxed = (GIdlNodeBoxed *)ctx->current_node;
+ boxed->members = g_list_append (boxed->members, field);
+ }
+ break;
+ case G_IDL_NODE_STRUCT:
+ {
+ GIdlNodeStruct *struct_;
+
+ struct_ = (GIdlNodeStruct *)ctx->current_node;
+ struct_->members = g_list_append (struct_->members, field);
+ }
+ break;
+ case G_IDL_NODE_UNION:
+ {
+ GIdlNodeUnion *union_;
+
+ union_ = (GIdlNodeUnion *)ctx->current_node;
+ union_->members = g_list_append (union_->members, field);
+ if (branch)
+ {
+ GIdlNodeConstant *constant;
+
+ constant = (GIdlNodeConstant *) g_idl_node_new (G_IDL_NODE_CONSTANT);
+ ((GIdlNode *)constant)->name = g_strdup (name);
+ constant->value = g_strdup (branch);
+ constant->type = union_->discriminator_type;
+ constant->deprecated = FALSE;
+
+ union_->discriminators = g_list_append (union_->discriminators, constant);
+ }
+ }
+ break;
+ }
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+start_enum (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if ((strcmp (element_name, "enum") == 0 && ctx->state == STATE_NAMESPACE) ||
+ (strcmp (element_name, "flags") == 0 && ctx->state == STATE_NAMESPACE))
+ {
+ const gchar *name;
+ const gchar *typename;
+ const gchar *typeinit;
+ const gchar *deprecated;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ typename = find_attribute ("type-name", attribute_names, attribute_values);
+ typeinit = find_attribute ("get-type", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else
+ {
+ GIdlNodeEnum *enum_;
+
+ if (strcmp (element_name, "enum") == 0)
+ enum_ = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_ENUM);
+ else
+ enum_ = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_FLAGS);
+ ((GIdlNode *)enum_)->name = g_strdup (name);
+ enum_->gtype_name = g_strdup (typename);
+ enum_->gtype_init = g_strdup (typeinit);
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ enum_->deprecated = TRUE;
+ else
+ enum_->deprecated = FALSE;
+
+ ctx->current_node = (GIdlNode *) enum_;
+ ctx->current_module->entries =
+ g_list_append (ctx->current_module->entries, enum_);
+
+ ctx->state = STATE_ENUM;
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+start_property (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "property") == 0 &&
+ (ctx->state == STATE_OBJECT ||
+ ctx->state == STATE_INTERFACE))
+ {
+ const gchar *name;
+ const gchar *type;
+ const gchar *readable;
+ const gchar *writable;
+ const gchar *construct;
+ const gchar *construct_only;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ type = find_attribute ("type", attribute_names, attribute_values);
+ readable = find_attribute ("readable", attribute_names, attribute_values);
+ writable = find_attribute ("writable", attribute_names, attribute_values);
+ construct = find_attribute ("construct", attribute_names, attribute_values);
+ construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (type == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "type");
+ else
+ {
+ GIdlNodeProperty *property;
+ GIdlNodeInterface *iface;
+
+ property = (GIdlNodeProperty *) g_idl_node_new (G_IDL_NODE_PROPERTY);
+
+ ((GIdlNode *)property)->name = g_strdup (name);
+
+ if (readable && strcmp (readable, "1") == 0)
+ property->readable = TRUE;
+ else
+ property->readable = FALSE;
+ if (writable && strcmp (writable, "1") == 0)
+ property->writable = TRUE;
+ else
+ property->writable = FALSE;
+ if (construct && strcmp (construct, "1") == 0)
+ property->construct = TRUE;
+ else
+ property->construct = FALSE;
+ if (construct_only && strcmp (construct_only, "1") == 0)
+ property->construct_only = TRUE;
+ else
+ property->construct_only = FALSE;
+
+ property->type = parse_type (type);
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface->members = g_list_append (iface->members, property);
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gint
+parse_value (const gchar *str)
+{
+ gchar *shift_op;
+
+ /* FIXME just a quick hack */
+ shift_op = strstr (str, "<<");
+
+ if (shift_op)
+ {
+ gint base, shift;
+
+ base = strtol (str, NULL, 10);
+ shift = strtol (shift_op + 3, NULL, 10);
+
+ return base << shift;
+ }
+ else
+ return strtol (str, NULL, 10);
+
+ return 0;
+}
+
+static gboolean
+start_member (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "member") == 0 &&
+ ctx->state == STATE_ENUM)
+ {
+ const gchar *name;
+ const gchar *value;
+ const gchar *deprecated;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ value = find_attribute ("value", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else
+ {
+ GIdlNodeEnum *enum_;
+ GIdlNodeValue *value_;
+
+ value_ = (GIdlNodeValue *) g_idl_node_new (G_IDL_NODE_VALUE);
+
+ ((GIdlNode *)value_)->name = g_strdup (name);
+
+ value_->value = parse_value (value);
+
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ value_->deprecated = TRUE;
+ else
+ value_->deprecated = FALSE;
+
+ enum_ = (GIdlNodeEnum *)ctx->current_node;
+ enum_->values = g_list_append (enum_->values, value_);
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+start_constant (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "constant") == 0 &&
+ (ctx->state == STATE_NAMESPACE ||
+ ctx->state == STATE_OBJECT ||
+ ctx->state == STATE_INTERFACE))
+ {
+ const gchar *name;
+ const gchar *type;
+ const gchar *value;
+ const gchar *deprecated;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ type = find_attribute ("type", attribute_names, attribute_values);
+ value = find_attribute ("value", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (type == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "type");
+ else if (value == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "value");
+ else
+ {
+ GIdlNodeConstant *constant;
+
+ constant = (GIdlNodeConstant *) g_idl_node_new (G_IDL_NODE_CONSTANT);
+
+ ((GIdlNode *)constant)->name = g_strdup (name);
+ constant->value = g_strdup (value);
+
+ constant->type = parse_type (type);
+
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ constant->deprecated = TRUE;
+ else
+ constant->deprecated = FALSE;
+
+ if (ctx->state == STATE_NAMESPACE)
+ {
+ ctx->current_node = (GIdlNode *) constant;
+ ctx->current_module->entries =
+ g_list_append (ctx->current_module->entries, constant);
+ }
+ else
+ {
+ GIdlNodeInterface *iface;
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface->members = g_list_append (iface->members, constant);
+ }
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+start_errordomain (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "errordomain") == 0 &&
+ ctx->state == STATE_NAMESPACE)
+ {
+ const gchar *name;
+ const gchar *getquark;
+ const gchar *codes;
+ const gchar *deprecated;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ getquark = find_attribute ("get-quark", attribute_names, attribute_values);
+ codes = find_attribute ("codes", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (getquark == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "getquark");
+ else if (codes == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "codes");
+ else
+ {
+ GIdlNodeErrorDomain *domain;
+
+ domain = (GIdlNodeErrorDomain *) g_idl_node_new (G_IDL_NODE_ERROR_DOMAIN);
+
+ ((GIdlNode *)domain)->name = g_strdup (name);
+ domain->getquark = g_strdup (getquark);
+ domain->codes = g_strdup (codes);
+
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ domain->deprecated = TRUE;
+ else
+ domain->deprecated = FALSE;
+
+ ctx->current_node = (GIdlNode *) domain;
+ ctx->current_module->entries =
+ g_list_append (ctx->current_module->entries, domain);
+
+ ctx->state = STATE_ERRORDOMAIN;
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+start_interface (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "interface") == 0 &&
+ ctx->state == STATE_NAMESPACE)
+ {
+ const gchar *name;
+ const gchar *typename;
+ const gchar *typeinit;
+ const gchar *deprecated;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ typename = find_attribute ("type-name", attribute_names, attribute_values);
+ typeinit = find_attribute ("get-type", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (typename == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "type-name");
+ else if (typeinit == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "get-type");
+ else
+ {
+ GIdlNodeInterface *iface;
+
+ iface = (GIdlNodeInterface *) g_idl_node_new (G_IDL_NODE_INTERFACE);
+ ((GIdlNode *)iface)->name = g_strdup (name);
+ iface->gtype_name = g_strdup (typename);
+ iface->gtype_init = g_strdup (typeinit);
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ iface->deprecated = TRUE;
+ else
+ iface->deprecated = FALSE;
+
+ ctx->current_node = (GIdlNode *) iface;
+ ctx->current_module->entries =
+ g_list_append (ctx->current_module->entries, iface);
+
+ ctx->state = STATE_INTERFACE;
+
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+start_object (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "object") == 0 &&
+ ctx->state == STATE_NAMESPACE)
+ {
+ const gchar *name;
+ const gchar *parent;
+ const gchar *typename;
+ const gchar *typeinit;
+ const gchar *deprecated;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ parent = find_attribute ("parent", attribute_names, attribute_values);
+ typename = find_attribute ("type-name", attribute_names, attribute_values);
+ typeinit = find_attribute ("get-type", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (typename == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "type-name");
+ else if (typeinit == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "get-type");
+ else
+ {
+ GIdlNodeInterface *iface;
+
+ iface = (GIdlNodeInterface *) g_idl_node_new (G_IDL_NODE_OBJECT);
+ ((GIdlNode *)iface)->name = g_strdup (name);
+ iface->gtype_name = g_strdup (typename);
+ iface->gtype_init = g_strdup (typeinit);
+ iface->parent = g_strdup (parent);
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ iface->deprecated = TRUE;
+ else
+ iface->deprecated = FALSE;
+
+ ctx->current_node = (GIdlNode *) iface;
+ ctx->current_module->entries =
+ g_list_append (ctx->current_module->entries, iface);
+
+ ctx->state = STATE_OBJECT;
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+start_return_type (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "return-type") == 0 &&
+ ctx->state == STATE_FUNCTION)
+ {
+ const gchar *type;
+ const gchar *nullok;
+ const gchar *transfer;
+
+ type = find_attribute ("type", attribute_names, attribute_values);
+ nullok = find_attribute ("null-ok", attribute_names, attribute_values);
+ transfer = find_attribute ("transfer", attribute_names, attribute_values);
+ if (type == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "type");
+ else
+ {
+ GIdlNodeParam *param;
+
+ param = (GIdlNodeParam *)g_idl_node_new (G_IDL_NODE_PARAM);
+ param->in = FALSE;
+ param->out = FALSE;
+ param->retval = TRUE;
+ if (nullok && strcmp (nullok, "1") == 0)
+ param->null_ok = TRUE;
+ else
+ param->null_ok = FALSE;
+ if (transfer && strcmp (transfer, "none") == 0)
+ {
+ param->transfer = FALSE;
+ param->shallow_transfer = FALSE;
+ }
+ else if (transfer && strcmp (transfer, "shallow") == 0)
+ {
+ param->transfer = FALSE;
+ param->shallow_transfer = TRUE;
+ }
+ else
+ {
+ param->transfer = TRUE;
+ param->shallow_transfer = FALSE;
+ }
+
+ param->type = parse_type (type);
+
+ switch (ctx->current_node->type)
+ {
+ case G_IDL_NODE_FUNCTION:
+ case G_IDL_NODE_CALLBACK:
+ {
+ GIdlNodeFunction *func = (GIdlNodeFunction *)ctx->current_node;
+ func->result = param;
+ }
+ break;
+ case G_IDL_NODE_SIGNAL:
+ {
+ GIdlNodeSignal *signal = (GIdlNodeSignal *)ctx->current_node;
+ signal->result = param;
+ }
+ break;
+ case G_IDL_NODE_VFUNC:
+ {
+ GIdlNodeVFunc *vfunc = (GIdlNodeVFunc *)ctx->current_node;
+ vfunc->result = param;
+ }
+ break;
+ }
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+start_signal (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "signal") == 0 &&
+ (ctx->state == STATE_OBJECT ||
+ ctx->state == STATE_INTERFACE))
+ {
+ const gchar *name;
+ const gchar *when;
+ const gchar *no_recurse;
+ const gchar *detailed;
+ const gchar *action;
+ const gchar *no_hooks;
+ const gchar *has_class_closure;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ when = find_attribute ("when", attribute_names, attribute_values);
+ no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
+ detailed = find_attribute ("detailed", attribute_names, attribute_values);
+ action = find_attribute ("action", attribute_names, attribute_values);
+ no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
+ has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (when == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "when");
+ else
+ {
+ GIdlNodeInterface *iface;
+ GIdlNodeSignal *signal;
+
+ signal = (GIdlNodeSignal *)g_idl_node_new (G_IDL_NODE_SIGNAL);
+
+ ((GIdlNode *)signal)->name = g_strdup (name);
+
+ signal->run_first = FALSE;
+ signal->run_last = FALSE;
+ signal->run_cleanup = FALSE;
+ if (strcmp (when, "FIRST") == 0)
+ signal->run_first = TRUE;
+ else if (strcmp (when, "LAST") == 0)
+ signal->run_last = TRUE;
+ else
+ signal->run_cleanup = TRUE;
+
+ if (no_recurse && strcmp (no_recurse, "1") == 0)
+ signal->no_recurse = TRUE;
+ else
+ signal->no_recurse = FALSE;
+ if (detailed && strcmp (detailed, "1") == 0)
+ signal->detailed = TRUE;
+ else
+ signal->detailed = FALSE;
+ if (action && strcmp (action, "1") == 0)
+ signal->action = TRUE;
+ else
+ signal->action = FALSE;
+ if (no_hooks && strcmp (no_hooks, "1") == 0)
+ signal->no_hooks = TRUE;
+ else
+ signal->no_hooks = FALSE;
+ if (has_class_closure && strcmp (has_class_closure, "1") == 0)
+ signal->has_class_closure = TRUE;
+ else
+ signal->has_class_closure = FALSE;
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface->members = g_list_append (iface->members, signal);
+
+ ctx->current_node = (GIdlNode *)signal;
+ ctx->state = STATE_FUNCTION;
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+start_vfunc (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "vfunc") == 0 &&
+ (ctx->state == STATE_OBJECT ||
+ ctx->state == STATE_INTERFACE))
+ {
+ const gchar *name;
+ const gchar *must_chain_up;
+ const gchar *override;
+ const gchar *is_class_closure;
+ const gchar *offset;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
+ override = find_attribute ("override", attribute_names, attribute_values);
+ is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
+ offset = find_attribute ("offset", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else
+ {
+ GIdlNodeInterface *iface;
+ GIdlNodeVFunc *vfunc;
+
+ vfunc = (GIdlNodeVFunc *)g_idl_node_new (G_IDL_NODE_VFUNC);
+
+ ((GIdlNode *)vfunc)->name = g_strdup (name);
+
+ if (must_chain_up && strcmp (must_chain_up, "1") == 0)
+ vfunc->must_chain_up = TRUE;
+ else
+ vfunc->must_chain_up = FALSE;
+
+ if (override && strcmp (override, "always") == 0)
+ {
+ vfunc->must_be_implemented = TRUE;
+ vfunc->must_not_be_implemented = FALSE;
+ }
+ else if (override && strcmp (override, "never") == 0)
+ {
+ vfunc->must_be_implemented = FALSE;
+ vfunc->must_not_be_implemented = TRUE;
+ }
+ else
+ {
+ vfunc->must_be_implemented = FALSE;
+ vfunc->must_not_be_implemented = FALSE;
+ }
+
+ if (is_class_closure && strcmp (is_class_closure, "1") == 0)
+ vfunc->is_class_closure = TRUE;
+ else
+ vfunc->is_class_closure = FALSE;
+
+ if (offset)
+ vfunc->offset = atoi (offset);
+ else
+ vfunc->offset = 0;
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface->members = g_list_append (iface->members, vfunc);
+
+ ctx->current_node = (GIdlNode *)vfunc;
+ ctx->state = STATE_FUNCTION;
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static gboolean
+start_struct (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "struct") == 0 &&
+ ctx->state == STATE_NAMESPACE)
+ {
+ const gchar *name;
+ const gchar *deprecated;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else
+ {
+ GIdlNodeStruct *struct_;
+
+ struct_ = (GIdlNodeStruct *) g_idl_node_new (G_IDL_NODE_STRUCT);
+
+ ((GIdlNode *)struct_)->name = g_strdup (name);
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ struct_->deprecated = TRUE;
+ else
+ struct_->deprecated = FALSE;
+
+ ctx->current_node = (GIdlNode *)struct_;
+ ctx->current_module->entries =
+ g_list_append (ctx->current_module->entries, struct_);
+
+ ctx->state = STATE_STRUCT;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static gboolean
+start_union (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "union") == 0 &&
+ ctx->state == STATE_NAMESPACE)
+ {
+ const gchar *name;
+ const gchar *deprecated;
+ const gchar *typename;
+ const gchar *typeinit;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+ typename = find_attribute ("type-name", attribute_names, attribute_values);
+ typeinit = find_attribute ("get-type", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else
+ {
+ GIdlNodeUnion *union_;
+
+ union_ = (GIdlNodeUnion *) g_idl_node_new (G_IDL_NODE_UNION);
+
+ ((GIdlNode *)union_)->name = g_strdup (name);
+ union_->gtype_name = g_strdup (typename);
+ union_->gtype_init = g_strdup (typeinit);
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ union_->deprecated = TRUE;
+ else
+ union_->deprecated = FALSE;
+
+ ctx->current_node = (GIdlNode *)union_;
+ ctx->current_module->entries =
+ g_list_append (ctx->current_module->entries, union_);
+
+ ctx->state = STATE_UNION;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+start_discriminator (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "discriminator") == 0 &&
+ ctx->state == STATE_UNION)
+ {
+ const gchar *type;
+ const gchar *offset;
+
+ type = find_attribute ("type", attribute_names, attribute_values);
+ offset = find_attribute ("offset", attribute_names, attribute_values);
+ if (type == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "type");
+ else if (offset == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "offset");
+ {
+ ((GIdlNodeUnion *)ctx->current_node)->discriminator_type
+ = parse_type (type);
+ ((GIdlNodeUnion *)ctx->current_node)->discriminator_offset
+ = atoi (offset);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+start_element_handler (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error)
+{
+ ParseContext *ctx = user_data;
+ gint i, line_number, char_number;
+
+ switch (element_name[0])
+ {
+ case 'a':
+ if (strcmp (element_name, "api") == 0 && ctx->state == STATE_START)
+ {
+ const gchar *version;
+
+ version = find_attribute ("version", attribute_names, attribute_values);
+
+ if (version == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "version");
+ else if (strcmp (version, "1.0") != 0)
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Unsupported version '%s'",
+ version);
+ else
+ ctx->state = STATE_ROOT;
+
+ goto out;
+ }
+ break;
+
+ case 'b':
+ if (start_boxed (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ break;
+
+ case 'c':
+ if (start_function (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (start_constant (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ break;
+
+ case 'd':
+ if (start_discriminator (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ break;
+
+ case 'e':
+ if (start_enum (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (start_errordomain (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ break;
+
+ case 'f':
+ if (start_function (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (start_field (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (start_enum (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+
+ break;
+
+ case 'i':
+ if (start_interface (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ if (strcmp (element_name, "implements") == 0 &&
+ ctx->state == STATE_OBJECT)
+ {
+ ctx->state = STATE_IMPLEMENTS;
+
+ goto out;
+ }
+ else if (strcmp (element_name, "interface") == 0 &&
+ ctx->state == STATE_IMPLEMENTS)
+ {
+ const gchar *name;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else
+ {
+ GIdlNodeInterface *iface;
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface ->interfaces = g_list_append (iface->interfaces, g_strdup (name));
+ }
+
+ goto out;
+ }
+ else if (strcmp (element_name, "interface") == 0 &&
+ ctx->state == STATE_REQUIRES)
+ {
+ const gchar *name;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else
+ {
+ GIdlNodeInterface *iface;
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
+ }
+
+ goto out;
+ }
+ break;
+
+ case 'm':
+ if (start_function (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (start_member (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ break;
+
+ case 'n':
+ if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_ROOT)
+ {
+ const gchar *name;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else
+ {
+ ctx->current_module = g_idl_module_new (name);
+ ctx->modules = g_list_append (ctx->modules, ctx->current_module);
+
+ ctx->state = STATE_NAMESPACE;
+ }
+
+ goto out;
+ }
+ break;
+
+ case 'o':
+ if (start_object (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (strcmp (element_name, "object") == 0 &&
+ ctx->state == STATE_REQUIRES)
+ {
+ const gchar *name;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else
+ {
+ GIdlNodeInterface *iface;
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
+ }
+
+ goto out;
+ }
+ break;
+
+ case 'p':
+ if (start_property (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (strcmp (element_name, "parameters") == 0 &&
+ ctx->state == STATE_FUNCTION)
+ {
+ ctx->state = STATE_PARAMETERS;
+
+ goto out;
+ }
+ else if (start_parameter (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+
+ break;
+
+ case 'r':
+ if (start_return_type (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (strcmp (element_name, "requires") == 0 &&
+ ctx->state == STATE_INTERFACE)
+ {
+ ctx->state = STATE_REQUIRES;
+
+ goto out;
+ }
+
+ break;
+
+ case 's':
+ if (start_signal (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (start_struct (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+
+ break;
+
+ case 'u':
+ if (start_union (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ break;
+
+ case 'v':
+ if (start_vfunc (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ break;
+ }
+
+ g_markup_parse_context_get_position (context, &line_number, &char_number);
+
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+ "Unexpected start tag '%s' on line %d char %d",
+ element_name,
+ line_number, char_number);
+
+ out: ;
+
+}
+
+static void
+end_element_handler (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{
+ ParseContext *ctx = user_data;
+
+ switch (ctx->state)
+ {
+ case STATE_START:
+ case STATE_END:
+ /* no need to GError here, GMarkup already catches this */
+ break;
+
+ case STATE_ROOT:
+ ctx->state = STATE_END;
+ break;
+
+ case STATE_NAMESPACE:
+ if (strcmp (element_name, "namespace") == 0)
+ {
+ ctx->current_module = NULL;
+ ctx->state = STATE_ROOT;
+ }
+ break;
+
+ case STATE_FUNCTION:
+ if (strcmp (element_name, "return-type") == 0)
+ /* do nothing */ ;
+
+ else if (ctx->current_node == g_list_last (ctx->current_module->entries)->data)
+ {
+ ctx->current_node = NULL;
+ ctx->state = STATE_NAMESPACE;
+ }
+ else
+ {
+ ctx->current_node = g_list_last (ctx->current_module->entries)->data;
+ if (ctx->current_node->type == G_IDL_NODE_INTERFACE)
+ ctx->state = STATE_INTERFACE;
+ else if (ctx->current_node->type == G_IDL_NODE_OBJECT)
+ ctx->state = STATE_OBJECT;
+ else if (ctx->current_node->type == G_IDL_NODE_BOXED)
+ ctx->state = STATE_BOXED;
+ else if (ctx->current_node->type == G_IDL_NODE_STRUCT)
+ ctx->state = STATE_STRUCT;
+ else if (ctx->current_node->type == G_IDL_NODE_UNION)
+ ctx->state = STATE_UNION;
+ }
+ break;
+
+ case STATE_OBJECT:
+ if (strcmp (element_name, "object") == 0)
+ {
+ ctx->current_node = NULL;
+ ctx->state = STATE_NAMESPACE;
+ }
+ break;
+
+ case STATE_ERRORDOMAIN:
+ if (strcmp (element_name, "errordomain") == 0)
+ {
+ ctx->current_node = NULL;
+ ctx->state = STATE_NAMESPACE;
+ }
+ break;
+
+ case STATE_INTERFACE:
+ if (strcmp (element_name, "interface") == 0)
+ {
+ ctx->current_node = NULL;
+ ctx->state = STATE_NAMESPACE;
+ }
+ break;
+
+ case STATE_ENUM:
+ if (strcmp (element_name, "enum") == 0 ||
+ strcmp (element_name, "flags") == 0)
+ {
+ ctx->current_node = NULL;
+ ctx->state = STATE_NAMESPACE;
+ }
+ break;
+
+ case STATE_BOXED:
+ if (strcmp (element_name, "boxed") == 0)
+ {
+ ctx->current_node = NULL;
+ ctx->state = STATE_NAMESPACE;
+ }
+ break;
+
+ case STATE_STRUCT:
+ if (strcmp (element_name, "struct") == 0)
+ {
+ ctx->current_node = NULL;
+ ctx->state = STATE_NAMESPACE;
+ }
+ break;
+ case STATE_UNION:
+ if (strcmp (element_name, "union") == 0)
+ {
+ ctx->current_node = NULL;
+ ctx->state = STATE_NAMESPACE;
+ }
+ break;
+
+ case STATE_IMPLEMENTS:
+ if (strcmp (element_name, "implements") == 0)
+ ctx->state = STATE_OBJECT;
+ break;
+ case STATE_REQUIRES:
+ ctx->state = STATE_INTERFACE;
+ break;
+ case STATE_PARAMETERS:
+ if (strcmp (element_name, "parameters") == 0)
+ ctx->state = STATE_FUNCTION;
+ break;
+ default:
+ g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
+ }
+}
+
+static void
+text_handler (GMarkupParseContext *context,
+ const gchar *text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{
+ /* FIXME warn about non-whitespace text */
+}
+
+static void
+cleanup (GMarkupParseContext *context,
+ GError *error,
+ gpointer user_data)
+{
+ ParseContext *ctx = user_data;
+ GList *m;
+
+ for (m = ctx->modules; m; m = m->next)
+ g_idl_module_free (m->data);
+ g_list_free (ctx->modules);
+ ctx->modules = NULL;
+
+ ctx->current_module = NULL;
+}
+
+static GMarkupParser parser =
+{
+ start_element_handler,
+ end_element_handler,
+ text_handler,
+ NULL,
+ cleanup
+};
+
+GList *
+g_idl_parse_string (const gchar *buffer,
+ gssize length,
+ GError **error)
+{
+ ParseContext ctx = { 0 };
+ GMarkupParseContext *context;
+
+ ctx.state = STATE_START;
+
+ context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
+ if (!g_markup_parse_context_parse (context, buffer, length, error))
+ goto out;
+
+ if (!g_markup_parse_context_end_parse (context, error))
+ goto out;
+
+ out:
+
+ g_markup_parse_context_free (context);
+
+ return ctx.modules;
+}
+
+GList *
+g_idl_parse_file (const gchar *filename,
+ GError **error)
+{
+ gchar *buffer;
+ gsize length;
+ GList *modules;
+
+ if (!g_file_get_contents (filename, &buffer, &length, error))
+ return NULL;
+
+ modules = g_idl_parse_string (buffer, length, error);
+
+ g_free (buffer);
+
+ return modules;
+}
+
+
diff --git a/gobject-introspection/gidlparser.h b/gobject-introspection/gidlparser.h
new file mode 100644
index 000000000..2d71aaa0d
--- /dev/null
+++ b/gobject-introspection/gidlparser.h
@@ -0,0 +1,38 @@
+/* GObject introspection: A parser for the XML IDL format
+ *
+ * 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.
+ */
+
+#ifndef __G_IDL_PARSER_H__
+#define __G_IDL_PARSER_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+
+GList *g_idl_parse_string (const gchar *buffer,
+ gssize length,
+ GError **error);
+GList *g_idl_parse_file (const gchar *filename,
+ GError **error);
+
+
+G_END_DECLS
+
+#endif /* __G_IDL_PARSER_H__ */
diff --git a/gobject-introspection/gmetadata.h b/gobject-introspection/gmetadata.h
new file mode 100644
index 000000000..7ca390c0d
--- /dev/null
+++ b/gobject-introspection/gmetadata.h
@@ -0,0 +1,539 @@
+/* GObject introspection: struct definitions for the binary
+ * metadata format, validation
+ *
+ * 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.
+ */
+
+#ifndef __G_METADATA_H__
+#define __G_METADATA_H__
+
+G_BEGIN_DECLS
+
+#define G_IDL_MAGIC "GOBJ\nMETADATA\r\n\032"
+
+enum
+{
+ BLOB_TYPE_INVALID,
+ BLOB_TYPE_FUNCTION,
+ BLOB_TYPE_CALLBACK,
+ BLOB_TYPE_STRUCT,
+ BLOB_TYPE_BOXED,
+ BLOB_TYPE_ENUM,
+ BLOB_TYPE_FLAGS,
+ BLOB_TYPE_OBJECT,
+ BLOB_TYPE_INTERFACE,
+ BLOB_TYPE_CONSTANT,
+ BLOB_TYPE_ERROR_DOMAIN,
+ BLOB_TYPE_UNION
+};
+
+typedef struct
+{
+ gchar magic[16];
+ guint8 major_version;
+ guint8 minor_version;
+ guint16 reserved;
+ guint16 n_entries;
+ guint16 n_local_entries;
+ guint32 directory;
+ guint32 n_annotations;
+ guint32 annotations;
+
+ guint32 size;
+ guint32 namespace;
+
+ guint16 entry_blob_size;
+ guint16 function_blob_size;
+ guint16 callback_blob_size;
+ guint16 signal_blob_size;
+ guint16 vfunc_blob_size;
+ guint16 arg_blob_size;
+ guint16 property_blob_size;
+ guint16 field_blob_size;
+ guint16 value_blob_size;
+ guint16 annotation_blob_size;
+ guint16 constant_blob_size;
+ guint16 error_domain_blob_size;
+
+ guint16 signature_blob_size;
+ guint16 enum_blob_size;
+ guint16 struct_blob_size;
+ guint16 object_blob_size;
+ guint16 interface_blob_size;
+ guint16 union_blob_size;
+
+ guint16 padding;
+} Header;
+
+typedef struct
+{
+ guint16 blob_type;
+
+ guint local : 1;
+ guint reserved :15;
+
+ guint32 name;
+ guint32 offset;
+} DirEntry;
+
+
+#define TYPE_POINTER_MASK 1 << 7
+#define TYPE_TAG_MASK 63
+
+typedef enum
+{
+ TYPE_TAG_VOID = 0,
+ TYPE_TAG_BOOLEAN = 1,
+ TYPE_TAG_INT8 = 2,
+ TYPE_TAG_UINT8 = 3,
+ TYPE_TAG_INT16 = 4,
+ TYPE_TAG_UINT16 = 5,
+ TYPE_TAG_INT32 = 6,
+ TYPE_TAG_UINT32 = 7,
+ TYPE_TAG_INT64 = 8,
+ TYPE_TAG_UINT64 = 9,
+ TYPE_TAG_INT = 10,
+ TYPE_TAG_UINT = 11,
+ TYPE_TAG_LONG = 12,
+ TYPE_TAG_ULONG = 13,
+ TYPE_TAG_SSIZE = 14,
+ TYPE_TAG_SIZE = 15,
+ TYPE_TAG_FLOAT = 16,
+ TYPE_TAG_DOUBLE = 17,
+ TYPE_TAG_UTF8 = 18,
+ TYPE_TAG_FILENAME = 19,
+ TYPE_TAG_ARRAY = 20,
+ TYPE_TAG_INTERFACE = 21,
+ TYPE_TAG_LIST = 22,
+ TYPE_TAG_SLIST = 23,
+ TYPE_TAG_HASH = 24,
+ TYPE_TAG_ERROR = 25
+} TypeTag;
+
+typedef union
+{
+ struct
+ {
+ guint reserved : 8;
+ guint reserved2 :16;
+ guint pointer : 1;
+ guint reserved3 : 2;
+ guint tag : 5;
+ };
+ guint32 offset;
+} SimpleTypeBlob;
+
+
+typedef struct
+{
+ guint32 name;
+
+ guint in : 1;
+ guint out : 1;
+ guint dipper : 1;
+ guint null_ok : 1;
+ guint optional : 1;
+ guint transfer_ownership : 1;
+ guint transfer_container_ownership : 1;
+ guint return_value : 1;
+ guint reserved :24;
+
+ SimpleTypeBlob arg_type;
+} ArgBlob;
+
+typedef struct
+{
+ SimpleTypeBlob return_type;
+
+ guint may_return_null : 1;
+ guint caller_owns_return_value : 1;
+ guint caller_owns_return_container : 1;
+ guint reserved :13;
+
+ guint16 n_arguments;
+
+ ArgBlob arguments[];
+} SignatureBlob;
+
+typedef struct
+{
+ guint16 blob_type; /* 1 */
+
+ guint deprecated : 1;
+ guint reserved :15;
+
+ guint32 name;
+} CommonBlob;
+
+typedef struct
+{
+ guint16 blob_type; /* 1 */
+
+ guint deprecated : 1;
+ guint setter : 1;
+ guint getter : 1;
+ guint constructor : 1;
+ guint wraps_vfunc : 1;
+ guint reserved : 1;
+ guint index :10;
+
+ guint32 name;
+ guint32 symbol;
+ guint32 signature;
+} FunctionBlob;
+
+typedef struct
+{
+ guint16 blob_type; /* 2 */
+
+ guint deprecated : 1;
+ guint reserved :15;
+
+ guint32 name;
+ guint32 signature;
+} CallbackBlob;
+
+typedef struct
+{
+ guint pointer :1;
+ guint reserved :2;
+ guint tag :5;
+ guint8 reserved2;
+ guint16 interface;
+} InterfaceTypeBlob;
+
+typedef struct
+{
+ guint pointer :1;
+ guint reserved :2;
+ guint tag :5;
+
+ guint zero_terminated :1;
+ guint has_length :1;
+ guint reserved2 :6;
+
+ guint16 length;
+
+ SimpleTypeBlob type;
+} ArrayTypeBlob;
+
+typedef struct
+{
+ guint pointer :1;
+ guint reserved :2;
+ guint tag :5;
+
+ guint8 reserved2;
+ guint16 n_types;
+
+ SimpleTypeBlob type[];
+} ParamTypeBlob;
+
+typedef struct
+{
+ guint pointer :1;
+ guint reserved :2;
+ guint tag :5;
+
+ guint8 reserved2;
+ guint16 n_domains;
+
+ guint16 domains[];
+} ErrorTypeBlob;
+
+typedef struct
+{
+ guint16 blob_type; /* 10 */
+
+ guint deprecated : 1;
+ guint reserved :15;
+
+ guint32 name;
+
+ guint32 get_quark;
+ guint16 error_codes;
+ guint16 reserved2;
+} ErrorDomainBlob;
+
+typedef struct
+{
+ guint deprecated : 1;
+ guint reserved :31;
+ guint32 name;
+ guint32 value;
+} ValueBlob;
+
+typedef struct
+{
+ guint32 name;
+
+ guint readable : 1;
+ guint writable : 1;
+ guint reserved : 6;
+ guint8 bits;
+
+ guint16 struct_offset;
+
+ SimpleTypeBlob type;
+} FieldBlob;
+
+typedef struct
+{
+ guint16 blob_type;
+ guint deprecated : 1;
+ guint unregistered :15;
+ guint32 name;
+
+ guint32 gtype_name;
+ guint32 gtype_init;
+} RegisteredTypeBlob;
+
+typedef struct
+{
+ guint16 blob_type;
+
+ guint deprecated : 1;
+ guint unregistered : 1;
+ guint reserved :14;
+
+ guint32 name;
+
+ guint32 gtype_name;
+ guint32 gtype_init;
+
+ guint16 n_fields;
+ guint16 n_methods;
+
+#if 0
+ /* variable-length parts of the blob */
+ FieldBlob fields[];
+ FunctionBlob methods[];
+#endif
+} StructBlob;
+
+typedef struct
+{
+ guint16 blob_type;
+ guint deprecated : 1;
+ guint unregistered : 1;
+ guint discriminated : 1;
+ guint reserved :13;
+ guint32 name;
+
+ guint32 gtype_name;
+ guint32 gtype_init;
+
+ guint16 n_fields;
+ guint16 n_functions;
+
+ gint32 discriminator_offset;
+ SimpleTypeBlob discriminator_type;
+
+#if 0
+ FieldBlob fields[];
+ FunctionBlob functions[];
+ ConstantBlob discriminator_values[]
+#endif
+} UnionBlob;
+
+typedef struct
+{
+ guint16 blob_type;
+
+ guint deprecated : 1;
+ guint unregistered : 1;
+ guint reserved :14;
+
+ guint32 name;
+
+ guint32 gtype_name;
+ guint32 gtype_init;
+
+ guint16 n_values;
+ guint16 reserved2;
+
+ ValueBlob values[];
+} EnumBlob;
+
+typedef struct
+{
+ guint32 name;
+
+ guint deprecated : 1;
+ guint readable : 1;
+ guint writable : 1;
+ guint construct : 1;
+ guint construct_only : 1;
+ guint reserved :27;
+
+ SimpleTypeBlob type;
+
+} PropertyBlob;
+
+typedef struct
+{
+ guint deprecated : 1;
+ guint run_first : 1;
+ guint run_last : 1;
+ guint run_cleanup : 1;
+ guint no_recurse : 1;
+ guint detailed : 1;
+ guint action : 1;
+ guint no_hooks : 1;
+ guint has_class_closure : 1;
+ guint true_stops_emit : 1;
+ guint reserved : 6;
+
+ guint16 class_closure;
+
+ guint32 name;
+
+ guint32 signature;
+} SignalBlob;
+
+typedef struct
+{
+ guint32 name;
+
+ guint must_chain_up : 1;
+ guint must_be_implemented : 1;
+ guint must_not_be_implemented : 1;
+ guint class_closure : 1;
+ guint reserved :12;
+ guint16 signal;
+
+ guint16 struct_offset;
+ guint16 reserved2;
+ guint32 signature;
+} VFuncBlob;
+
+typedef struct
+{
+ guint16 blob_type; /* 7 */
+ guint deprecated : 1;
+ guint reserved :15;
+ guint32 name;
+
+ guint32 gtype_name;
+ guint32 gtype_init;
+
+ guint16 parent;
+
+ guint16 n_interfaces;
+ guint16 n_fields;
+ guint16 n_properties;
+ guint16 n_methods;
+ guint16 n_signals;
+ guint16 n_vfuncs;
+ guint16 n_constants;
+
+ guint16 interfaces[];
+
+#if 0
+ /* variable-length parts of the blob */
+ FieldBlob fields[];
+ PropertyBlob properties[];
+ FunctionBlob methods[];
+ SignalBlob signals[];
+ VFuncBlob vfuncs[];
+ ConstantBlob constants[];
+#endif
+} ObjectBlob;
+
+typedef struct
+{
+ guint16 blob_type;
+ guint deprecated : 1;
+ guint reserved :15;
+ guint32 name;
+
+ guint32 gtype_name;
+ guint32 gtype_init;
+
+ guint16 n_prerequisites;
+ guint16 n_properties;
+ guint16 n_methods;
+ guint16 n_signals;
+ guint16 n_vfuncs;
+ guint16 n_constants;
+
+ guint16 prerequisites[];
+
+#if 0
+ /* variable-length parts of the blob */
+ PropertyBlob properties[];
+ FunctionBlob methods[];
+ SignalBlob signals[];
+ VFuncBlob vfuncs[];
+ ConstantBlob constants[];
+#endif
+} InterfaceBlob;
+
+
+typedef struct
+{
+ guint16 blob_type;
+ guint deprecated : 1;
+ guint reserved :15;
+ guint32 name;
+
+ SimpleTypeBlob type;
+
+ guint32 size;
+ guint32 offset;
+} ConstantBlob;
+
+typedef struct
+{
+ guint32 offset;
+ guint32 name;
+ guint32 value;
+} AnnotationBlob;
+
+
+
+DirEntry *g_metadata_get_dir_entry (const guchar *metadata,
+ guint16 index);
+
+void g_metadata_check_sanity (void);
+
+#define g_metadata_get_string(metadata,offset) ((const gchar*)&(metadata)[(offset)])
+
+
+typedef enum
+{
+ G_METADATA_ERROR_INVALID,
+ G_METADATA_ERROR_INVALID_HEADER,
+ G_METADATA_ERROR_INVALID_DIRECTORY,
+ G_METADATA_ERROR_INVALID_ENTRY,
+ G_METADATA_ERROR_INVALID_BLOB
+} GMetadataError;
+
+#define G_METADATA_ERROR (g_metadata_error_quark ())
+
+GQuark g_metadata_error_quark (void);
+
+gboolean g_metadata_validate (const guchar *data,
+ guint len,
+ GError **error);
+
+
+G_END_DECLS
+
+#endif /* __G_METADATA_H__ */
+