From 49b2d0afbf9f752d899b782c5b01587ebeaf3985 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 5 Aug 2008 15:12:11 +0000 Subject: Rename some things to use GIR instead of GIDL (Phillip Van Hoof, Colin Walters) svn path=/branches/gir-compiler/; revision=299 --- tools/Makefile.am | 30 +- tools/gidlmodule.c | 215 ------ tools/gidlmodule.h | 48 -- tools/gidlnode.c | 2078 ---------------------------------------------------- tools/gidlnode.h | 334 --------- tools/gidlparser.c | 2055 --------------------------------------------------- tools/gidlparser.h | 38 - tools/gidlwriter.c | 529 ------------- tools/gidlwriter.h | 26 - tools/girmodule.c | 215 ++++++ tools/girmodule.h | 48 ++ tools/girnode.c | 2078 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/girnode.h | 334 +++++++++ tools/girparser.c | 2056 +++++++++++++++++++++++++++++++++++++++++++++++++++ tools/girparser.h | 38 + tools/girwriter.c | 529 +++++++++++++ tools/girwriter.h | 26 + 17 files changed, 5339 insertions(+), 5338 deletions(-) delete mode 100644 tools/gidlmodule.c delete mode 100644 tools/gidlmodule.h delete mode 100644 tools/gidlnode.c delete mode 100644 tools/gidlnode.h delete mode 100644 tools/gidlparser.c delete mode 100644 tools/gidlparser.h delete mode 100644 tools/gidlwriter.c delete mode 100644 tools/gidlwriter.h create mode 100644 tools/girmodule.c create mode 100644 tools/girmodule.h create mode 100644 tools/girnode.c create mode 100644 tools/girnode.h create mode 100644 tools/girparser.c create mode 100644 tools/girparser.h create mode 100644 tools/girwriter.c create mode 100644 tools/girwriter.h diff --git a/tools/Makefile.am b/tools/Makefile.am index 6ebfc382..2fb0e66b 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -8,29 +8,29 @@ INCLUDES = \ EXTRA_DIST = g-ir-scanner noinst_LTLIBRARIES = libgirepository-parser.la -bin_PROGRAMS = g-idl-compiler g-idl-generate +bin_PROGRAMS = g-ir-compiler g-ir-generate bin_SCRIPTS = g-ir-scanner libgirepository_parser_la_SOURCES = \ - gidlmodule.c \ - gidlmodule.h \ - gidlnode.c \ - gidlnode.h \ - gidlparser.c \ - gidlparser.h + girmodule.c \ + girmodule.h \ + girnode.c \ + girnode.h \ + girparser.c \ + girparser.h libgirepository_parser_la_CFLAGS = $(GIREPO_CFLAGS) -g_idl_compiler_SOURCES = compiler.c -g_idl_compiler_CFLAGS = $(GIREPO_CFLAGS) -g_idl_compiler_LDADD = $(GIREPO_LIBS) $(top_builddir)/girepository/libgirepository.la libgirepository-parser.la +g_ir_compiler_SOURCES = compiler.c +g_ir_compiler_CFLAGS = $(GIREPO_CFLAGS) +g_ir_compiler_LDADD = $(GIREPO_LIBS) $(top_builddir)/girepository/libgirepository.la libgirepository-parser.la -g_idl_generate_SOURCES = generate.c -g_idl_generate_CFLAGS = $(GIREPO_CFLAGS) -g_idl_generate_LDADD = $(GIREPO_LIBS) $(top_builddir)/girepository/libgirepository.la +g_ir_generate_SOURCES = generate.c +g_ir_generate_CFLAGS = $(GIREPO_CFLAGS) +g_ir_generate_LDADD = $(GIREPO_LIBS) $(top_builddir)/girepository/libgirepository.la GCOVSOURCES = \ $(libgirepository_la_SOURCES) \ - $(g_idl_compiler_SOURCES) \ - $(g_idl_generate_SOURCES) + $(g_ir_compiler_SOURCES) \ + $(g_ir_generate_SOURCES) include $(top_srcdir)/gcov.mak diff --git a/tools/gidlmodule.c b/tools/gidlmodule.c deleted file mode 100644 index d543346b..00000000 --- a/tools/gidlmodule.c +++ /dev/null @@ -1,215 +0,0 @@ -/* 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 -#include - -#include "gidlmodule.h" -#include "gidlnode.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, const gchar *shared_library) -{ - GIdlModule *module; - - module = g_new (GIdlModule, 1); - - module->name = g_strdup (name); - if (shared_library) - module->shared_library = g_strdup (shared_library); - else - module->shared_library = NULL; - 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); -} - -GTypelib * -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->shared_library = (module->shared_library? - write_string (module->shared_library, strings, data, &header_size) - : 0); - 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; - return g_typelib_new_from_memory (metadata, length); -} - diff --git a/tools/gidlmodule.h b/tools/gidlmodule.h deleted file mode 100644 index 0814ed51..00000000 --- a/tools/gidlmodule.h +++ /dev/null @@ -1,48 +0,0 @@ -/* 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 -#include "gtypelib.h" - -G_BEGIN_DECLS - - -typedef struct _GIdlModule GIdlModule; - -struct _GIdlModule -{ - gchar *name; - gchar *shared_library; - GList *entries; -}; - -GIdlModule *g_idl_module_new (const gchar *name, - const gchar *module_filename); -void g_idl_module_free (GIdlModule *module); - -GTypelib * g_idl_module_build_metadata (GIdlModule *module, - GList *modules); - -G_END_DECLS - -#endif /* __G_IDL_MODULE_H__ */ diff --git a/tools/gidlnode.c b/tools/gidlnode.c deleted file mode 100644 index 09f3f072..00000000 --- a/tools/gidlnode.c +++ /dev/null @@ -1,2078 +0,0 @@ -/* 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 -#include -#include - -#include "gidlmodule.h" -#include "gidlnode.h" -#include "gtypelib.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 ("%lu strings (%lu before sharing), %lu bytes (%lu before sharing)", - unique_string_count, string_count, unique_string_size, string_size); - g_message ("%lu types (%lu 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: - case G_IDL_NODE_CALLBACK: - 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: - { - 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 %p 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: - { - 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 %p type %d full size %d", node, node->type, size); - - return size; -} - -int -g_idl_node_cmp (GIdlNode *node, - GIdlNode *other) -{ - if (node->type < other->type) - return -1; - else if (node->type > other->type) - return 1; - else - return strcmp (node->name, other->name); -} - -gboolean -g_idl_node_can_have_member (GIdlNode *node) -{ - switch (node->type) - { - case G_IDL_NODE_OBJECT: - case G_IDL_NODE_INTERFACE: - case G_IDL_NODE_BOXED: - case G_IDL_NODE_STRUCT: - case G_IDL_NODE_UNION: - return TRUE; - }; - return FALSE; -} - -void -g_idl_node_add_member (GIdlNode *node, - GIdlNodeFunction *member) -{ - g_return_if_fail (node != NULL); - g_return_if_fail (member != NULL); - - switch (node->type) - { - case G_IDL_NODE_OBJECT: - case G_IDL_NODE_INTERFACE: - { - GIdlNodeInterface *iface = (GIdlNodeInterface *)node; - iface->members = - g_list_insert_sorted (iface->members, member, - (GCompareFunc) g_idl_node_cmp); - break; - } - case G_IDL_NODE_BOXED: - { - GIdlNodeBoxed *boxed = (GIdlNodeBoxed *)node; - boxed->members = - g_list_insert_sorted (boxed->members, member, - (GCompareFunc) g_idl_node_cmp); - break; - } - case G_IDL_NODE_STRUCT: - { - GIdlNodeStruct *struct_ = (GIdlNodeStruct *)node; - struct_->members = - g_list_insert_sorted (struct_->members, member, - (GCompareFunc) g_idl_node_cmp); - break; - } - case G_IDL_NODE_UNION: - { - GIdlNodeUnion *union_ = (GIdlNodeUnion *)node; - union_->members = - g_list_insert_sorted (union_->members, member, - (GCompareFunc) g_idl_node_cmp); - break; - } - default: - g_error ("Cannot add a member to unknown type tag type %d\n", - node->type); - break; - } -} - -const gchar * -g_idl_node_param_direction_string (GIdlNodeParam * node) -{ - if (node->out) - { - if (node->in) - return "in-out"; - else - return "out"; - } - return "in"; -} - -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; - - 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; - 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; - 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; - 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; - 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; - - *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; - - 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; - - 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; - default: - g_assert_not_reached (); - } - - 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/tools/gidlnode.h b/tools/gidlnode.h deleted file mode 100644 index 32a9a939..00000000 --- a/tools/gidlnode.h +++ /dev/null @@ -1,334 +0,0 @@ -/* 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 - -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); -int g_idl_node_cmp (GIdlNode *node, - GIdlNode *other); -gboolean g_idl_node_can_have_member (GIdlNode *node); -void g_idl_node_add_member (GIdlNode *node, - GIdlNodeFunction *member); -guint32 write_string (const gchar *str, - GHashTable *strings, - guchar *data, - guint32 *offset); - -const gchar * g_idl_node_param_direction_string (GIdlNodeParam * node); - -G_END_DECLS - -#endif /* __G_IDL_NODE_H__ */ diff --git a/tools/gidlparser.c b/tools/gidlparser.c deleted file mode 100644 index 52b3d788..00000000 --- a/tools/gidlparser.c +++ /dev/null @@ -1,2055 +0,0 @@ -/* 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 -#include -#include - -#include -#include "gidlmodule.h" -#include "gidlnode.h" -#include "gtypelib.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 }, - { "bool", TYPE_TAG_BOOLEAN, 0 }, - { "gboolean", TYPE_TAG_BOOLEAN, 0 }, -#if 0 - { "char", TYPE_TAG_INT8, 0 }, - { "gchar", TYPE_TAG_INT8, 0 }, - { "guchar", TYPE_TAG_UINT8, 0 }, -#endif - { "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; - default: - g_assert_not_reached (); - } - - 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; - default: - g_assert_not_reached (); - } - } - - 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; - default: - g_assert_not_reached (); - } - } - 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; - default: - g_assert_not_reached (); - } - } - - 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 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, *shared_library; - - name = find_attribute ("name", attribute_names, attribute_values); - shared_library = find_attribute ("shared-library", attribute_names, attribute_values); - - if (name == NULL) - MISSING_ATTRIBUTE (error, element_name, "name"); - else - { - ctx->current_module = g_idl_module_new (name, shared_library); - 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: - if (strcmp (element_name, "requires") == 0) - 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/tools/gidlparser.h b/tools/gidlparser.h deleted file mode 100644 index 2d71aaa0..00000000 --- a/tools/gidlparser.h +++ /dev/null @@ -1,38 +0,0 @@ -/* 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 - -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/tools/gidlwriter.c b/tools/gidlwriter.c deleted file mode 100644 index c99d1deb..00000000 --- a/tools/gidlwriter.c +++ /dev/null @@ -1,529 +0,0 @@ -/* GObject introspection: gen-introspect - * - * Copyright (C) 2007 Jürg Billeter - * Copyright (C) 2007 Johan Dahlin - * - * 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.1 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. - * - * Author: - * Jürg Billeter - */ - -#include -#include -#include "scanner.h" -#include "gidlnode.h" - -typedef struct { - int indent; - FILE *output; -} GIdlWriter; - -static void node_generate (GIdlWriter * writer, GIdlNode * node); - -static void -g_writer_write_inline (GIdlWriter * writer, const char *s) -{ - fprintf (writer->output, "%s", s); -} - -static void -g_writer_write (GIdlWriter * writer, const char *s) -{ - int i; - for (i = 0; i < writer->indent; i++) - { - fprintf (writer->output, "\t"); - } - - g_writer_write_inline (writer, s); -} - -static void -g_writer_write_indent (GIdlWriter * writer, const char *s) -{ - g_writer_write (writer, s); - writer->indent++; -} - -static void -g_writer_write_unindent (GIdlWriter * writer, const char *s) -{ - writer->indent--; - g_writer_write (writer, s); -} - -static void -field_generate (GIdlWriter * writer, GIdlNodeField * node) -{ - char *markup = - g_markup_printf_escaped ("\n", - node->node.name, node->type->unparsed); - g_writer_write (writer, markup); - g_free (markup); -} - -static void -value_generate (GIdlWriter * writer, GIdlNodeValue * node) -{ - char *markup = - g_markup_printf_escaped ("\n", - node->node.name, node->value); - g_writer_write (writer, markup); - g_free (markup); -} - -static void -constant_generate (GIdlWriter * writer, GIdlNodeConstant * node) -{ - char *markup = - g_markup_printf_escaped - ("\n", node->node.name, - node->type->unparsed, node->value); - g_writer_write (writer, markup); - g_free (markup); -} - -static void -property_generate (GIdlWriter * writer, GIdlNodeProperty * node) -{ - char *markup = - g_markup_printf_escaped ("\n", - node->node.name, - node->type->unparsed, - node->readable ? "1" : "0", - node->writable ? "1" : "0", - node->construct ? "1" : "0", - node->construct_only ? "1" : "0"); - g_writer_write (writer, markup); - g_free (markup); -} - -static void -function_generate (GIdlWriter * writer, GIdlNodeFunction * node) -{ - const char *tag_name; - GString *markup_s; - gchar *markup; - - if (node->node.type == G_IDL_NODE_CALLBACK) - tag_name = "callback"; - else if (node->is_constructor) - tag_name = "constructor"; - else if (node->is_method) - tag_name = "method"; - else - tag_name = "function"; - - markup_s = g_string_new ("<"); - g_string_append_printf (markup_s, - "%s name=\"%s\"", - tag_name, node->node.name); - - if (node->node.type != G_IDL_NODE_CALLBACK) - g_string_append_printf (markup_s, - g_markup_printf_escaped (" symbol=\"%s\"", node->symbol)); - - if (node->deprecated) - g_string_append_printf (markup_s, " deprecated=\"1\""); - - g_string_append (markup_s, ">\n"); - - g_writer_write_indent (writer, markup_s->str); - g_string_free (markup_s, TRUE); - - markup_s = - g_string_new (g_markup_printf_escaped ("result->type->unparsed)); - - if (node->result->transfer) - g_string_append (markup_s, g_markup_printf_escaped (" transfer=\"full\"/>\n")); - else - g_string_append (markup_s, "/>\n"); - - g_writer_write (writer, markup_s->str); - g_string_free (markup_s, TRUE); - - if (node->parameters != NULL) - { - GList *l; - g_writer_write_indent (writer, "\n"); - for (l = node->parameters; l != NULL; l = l->next) - { - GIdlNodeParam *param = l->data; - const gchar *direction = g_idl_node_param_direction_string (param); - - markup_s = g_string_new ("node.name); - - g_string_append (markup_s, - g_markup_printf_escaped (" type=\"%s\"", - param->type->unparsed)); - - if (param->transfer) - g_string_append (markup_s, - g_markup_printf_escaped (" transfer=\"full\"")); - - if (param->null_ok) - g_string_append (markup_s, - g_markup_printf_escaped (" null-ok=\"1\"")); - - if (strcmp (direction, "in") != 0) - g_string_append (markup_s, - g_markup_printf_escaped (" direction=\"%s\"", - direction)); - - g_string_append (markup_s, "/>\n"); - - g_writer_write (writer, markup_s->str); - g_string_free (markup_s, TRUE); - } - g_writer_write_unindent (writer, "\n"); - } - markup = g_strdup_printf ("\n", tag_name); - g_writer_write_unindent (writer, markup); - g_free (markup); -} - -static void -vfunc_generate (GIdlWriter * writer, GIdlNodeVFunc * node) -{ - char *markup = - g_markup_printf_escaped ("\n", node->node.name); - g_writer_write_indent (writer, markup); - g_free (markup); - markup = - g_markup_printf_escaped ("\n", - node->result->type->unparsed); - g_writer_write (writer, markup); - g_free (markup); - if (node->parameters != NULL) - { - GList *l; - g_writer_write_indent (writer, "\n"); - for (l = node->parameters; l != NULL; l = l->next) - { - GIdlNodeParam *param = l->data; - markup = - g_markup_printf_escaped ("\n", - param->node.name, param->type->unparsed); - g_writer_write (writer, markup); - g_free (markup); - } - g_writer_write_unindent (writer, "\n"); - } - g_writer_write_unindent (writer, "\n"); -} - -static void -signal_generate (GIdlWriter * writer, GIdlNodeSignal * node) -{ - char *markup; - const char *when = "LAST"; - if (node->run_first) - { - when = "FIRST"; - } - else if (node->run_cleanup) - { - when = "CLEANUP"; - } - markup = - g_markup_printf_escaped ("\n", - node->node.name, when); - g_writer_write_indent (writer, markup); - g_free (markup); - markup = - g_markup_printf_escaped ("\n", - node->result->type->unparsed); - g_writer_write (writer, markup); - g_free (markup); - if (node->parameters != NULL) - { - GList *l; - g_writer_write_indent (writer, "\n"); - for (l = node->parameters; l != NULL; l = l->next) - { - GIdlNodeParam *param = l->data; - markup = - g_markup_printf_escaped ("\n", - param->node.name, param->type->unparsed); - g_writer_write (writer, markup); - g_free (markup); - } - g_writer_write_unindent (writer, "\n"); - } - g_writer_write_unindent (writer, "\n"); -} - -static void -interface_generate (GIdlWriter * writer, GIdlNodeInterface * node) -{ - GList *l; - char *markup; - if (node->node.type == G_IDL_NODE_OBJECT) - { - markup = - g_markup_printf_escaped ("\n", - node->node.name, - node->parent, - node->gtype_name, - node->gtype_init); - } - else if (node->node.type == G_IDL_NODE_INTERFACE) - { - markup = - g_markup_printf_escaped - ("\n", - node->node.name, node->gtype_name, node->gtype_init); - } - - g_writer_write_indent (writer, markup); - g_free (markup); - if (node->node.type == G_IDL_NODE_OBJECT && node->interfaces != NULL) - { - GList *l; - g_writer_write_indent (writer, "\n"); - for (l = node->interfaces; l != NULL; l = l->next) - { - markup = - g_markup_printf_escaped ("\n", - (char *) l->data); - g_writer_write (writer, markup); - g_free (markup); - } - g_writer_write_unindent (writer, "\n"); - } - else if (node->node.type == G_IDL_NODE_INTERFACE - && node->prerequisites != NULL) - { - GList *l; - g_writer_write_indent (writer, "\n"); - for (l = node->prerequisites; l != NULL; l = l->next) - { - markup = - g_markup_printf_escaped ("\n", - (char *) l->data); - g_writer_write (writer, markup); - g_free (markup); - } - g_writer_write_unindent (writer, "\n"); - } - - for (l = node->members; l != NULL; l = l->next) - { - node_generate (writer, l->data); - } - - if (node->node.type == G_IDL_NODE_OBJECT) - { - g_writer_write_unindent (writer, "\n"); - } - else if (node->node.type == G_IDL_NODE_INTERFACE) - { - g_writer_write_unindent (writer, "\n"); - } -} - -static void -struct_generate (GIdlWriter * writer, GIdlNodeStruct * node) -{ - GList *l; - char *markup = - g_markup_printf_escaped ("\n", node->node.name); - g_writer_write_indent (writer, markup); - g_free (markup); - for (l = node->members; l != NULL; l = l->next) - { - node_generate (writer, l->data); - } - g_writer_write_unindent (writer, "\n"); -} - -static void -union_generate (GIdlWriter * writer, GIdlNodeUnion * node) -{ - GList *l; - char *markup = - g_markup_printf_escaped ("\n", node->node.name); - g_writer_write_indent (writer, markup); - g_free (markup); - for (l = node->members; l != NULL; l = l->next) - { - node_generate (writer, l->data); - } - g_writer_write_unindent (writer, "\n"); -} - -static void -boxed_generate (GIdlWriter * writer, GIdlNodeBoxed * node) -{ - GList *l; - char *markup = - g_markup_printf_escaped - ("\n", - node->node.name, node->gtype_name, node->gtype_init); - g_writer_write_indent (writer, markup); - g_free (markup); - for (l = node->members; l != NULL; l = l->next) - { - node_generate (writer, l->data); - } - g_writer_write_unindent (writer, "\n"); -} - -static void -enum_generate (GIdlWriter * writer, GIdlNodeEnum * node) -{ - GList *l; - GString *markup_s; - char *markup; - const char *tag_name = NULL; - - if (node->node.type == G_IDL_NODE_ENUM) - { - tag_name = "enum"; - } - else if (node->node.type == G_IDL_NODE_FLAGS) - { - tag_name = "flags"; - } - - markup_s = g_string_new ("<"); - g_string_append_printf (markup_s, - "%s name=\"%s\"", - tag_name, node->node.name); - - if (node->gtype_name != NULL) - g_string_append_printf (markup_s, - g_markup_printf_escaped (" type-name=\"%s\"", node->gtype_name)); - - if (node->gtype_init != NULL) - g_string_append_printf (markup_s, - g_markup_printf_escaped (" get-type=\"%s\"", node->gtype_init)); - - if (node->deprecated) - g_string_append_printf (markup_s, " deprecated=\"1\""); - - g_string_append (markup_s, ">\n"); - - g_writer_write_indent (writer, markup_s->str); - g_string_free (markup_s, TRUE); - - for (l = node->values; l != NULL; l = l->next) - { - node_generate (writer, l->data); - } - - markup = g_strdup_printf ("\n", tag_name); - g_writer_write_unindent (writer, markup); - g_free (markup); -} - -static void -node_generate (GIdlWriter * writer, GIdlNode * node) -{ - switch (node->type) - { - case G_IDL_NODE_FUNCTION: - case G_IDL_NODE_CALLBACK: - function_generate (writer, (GIdlNodeFunction *) node); - break; - case G_IDL_NODE_VFUNC: - vfunc_generate (writer, (GIdlNodeVFunc *) node); - break; - case G_IDL_NODE_OBJECT: - case G_IDL_NODE_INTERFACE: - interface_generate (writer, (GIdlNodeInterface *) node); - break; - case G_IDL_NODE_STRUCT: - struct_generate (writer, (GIdlNodeStruct *) node); - break; - case G_IDL_NODE_UNION: - union_generate (writer, (GIdlNodeUnion *) node); - break; - case G_IDL_NODE_BOXED: - boxed_generate (writer, (GIdlNodeBoxed *) node); - break; - case G_IDL_NODE_ENUM: - case G_IDL_NODE_FLAGS: - enum_generate (writer, (GIdlNodeEnum *) node); - break; - case G_IDL_NODE_PROPERTY: - property_generate (writer, (GIdlNodeProperty *) node); - break; - case G_IDL_NODE_FIELD: - field_generate (writer, (GIdlNodeField *) node); - break; - case G_IDL_NODE_SIGNAL: - signal_generate (writer, (GIdlNodeSignal *) node); - break; - case G_IDL_NODE_VALUE: - value_generate (writer, (GIdlNodeValue *) node); - break; - case G_IDL_NODE_CONSTANT: - constant_generate (writer, (GIdlNodeConstant *) node); - break; - default: - g_assert_not_reached (); - } -} - -static void -g_writer_write_module (GIdlWriter * writer, GIdlModule * module) -{ - GList *l; - char *markup = - g_markup_printf_escaped ("\n", module->name); - g_writer_write_indent (writer, markup); - g_free (markup); - for (l = module->entries; l != NULL; l = l->next) - { - node_generate (writer, l->data); - } - g_writer_write_unindent (writer, "\n"); -} - -void -g_idl_writer_save_file (GIdlModule *module, - const gchar *filename) -{ - GIdlWriter *writer; - - writer = g_new0 (GIdlWriter, 1); - - if (!filename) - writer->output = stdout; - else - writer->output = fopen (filename, "w"); - - g_writer_write (writer, "\n"); - g_writer_write_indent (writer, "\n"); - g_writer_write_module (writer, module); - g_writer_write_unindent (writer, "\n"); - - if (filename) - fclose (writer->output); -} diff --git a/tools/gidlwriter.h b/tools/gidlwriter.h deleted file mode 100644 index 5d41a0c6..00000000 --- a/tools/gidlwriter.h +++ /dev/null @@ -1,26 +0,0 @@ -/* GObject introspection: IDL writer - * - * Copyright (C) 2007 Johan Dahlin - * - * 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_WRITER_H__ -#define __G_IDL_WRITER_H__ - -void g_idl_writer_save_file (GIdlModule *module, const gchar *filename); - -#endif /* __G_IDL_WRITER_H__ */ diff --git a/tools/girmodule.c b/tools/girmodule.c new file mode 100644 index 00000000..d543346b --- /dev/null +++ b/tools/girmodule.c @@ -0,0 +1,215 @@ +/* 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 +#include + +#include "gidlmodule.h" +#include "gidlnode.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, const gchar *shared_library) +{ + GIdlModule *module; + + module = g_new (GIdlModule, 1); + + module->name = g_strdup (name); + if (shared_library) + module->shared_library = g_strdup (shared_library); + else + module->shared_library = NULL; + 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); +} + +GTypelib * +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->shared_library = (module->shared_library? + write_string (module->shared_library, strings, data, &header_size) + : 0); + 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; + return g_typelib_new_from_memory (metadata, length); +} + diff --git a/tools/girmodule.h b/tools/girmodule.h new file mode 100644 index 00000000..0814ed51 --- /dev/null +++ b/tools/girmodule.h @@ -0,0 +1,48 @@ +/* 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 +#include "gtypelib.h" + +G_BEGIN_DECLS + + +typedef struct _GIdlModule GIdlModule; + +struct _GIdlModule +{ + gchar *name; + gchar *shared_library; + GList *entries; +}; + +GIdlModule *g_idl_module_new (const gchar *name, + const gchar *module_filename); +void g_idl_module_free (GIdlModule *module); + +GTypelib * g_idl_module_build_metadata (GIdlModule *module, + GList *modules); + +G_END_DECLS + +#endif /* __G_IDL_MODULE_H__ */ diff --git a/tools/girnode.c b/tools/girnode.c new file mode 100644 index 00000000..09f3f072 --- /dev/null +++ b/tools/girnode.c @@ -0,0 +1,2078 @@ +/* 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 +#include +#include + +#include "gidlmodule.h" +#include "gidlnode.h" +#include "gtypelib.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 ("%lu strings (%lu before sharing), %lu bytes (%lu before sharing)", + unique_string_count, string_count, unique_string_size, string_size); + g_message ("%lu types (%lu 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: + case G_IDL_NODE_CALLBACK: + 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: + { + 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 %p 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: + { + 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 %p type %d full size %d", node, node->type, size); + + return size; +} + +int +g_idl_node_cmp (GIdlNode *node, + GIdlNode *other) +{ + if (node->type < other->type) + return -1; + else if (node->type > other->type) + return 1; + else + return strcmp (node->name, other->name); +} + +gboolean +g_idl_node_can_have_member (GIdlNode *node) +{ + switch (node->type) + { + case G_IDL_NODE_OBJECT: + case G_IDL_NODE_INTERFACE: + case G_IDL_NODE_BOXED: + case G_IDL_NODE_STRUCT: + case G_IDL_NODE_UNION: + return TRUE; + }; + return FALSE; +} + +void +g_idl_node_add_member (GIdlNode *node, + GIdlNodeFunction *member) +{ + g_return_if_fail (node != NULL); + g_return_if_fail (member != NULL); + + switch (node->type) + { + case G_IDL_NODE_OBJECT: + case G_IDL_NODE_INTERFACE: + { + GIdlNodeInterface *iface = (GIdlNodeInterface *)node; + iface->members = + g_list_insert_sorted (iface->members, member, + (GCompareFunc) g_idl_node_cmp); + break; + } + case G_IDL_NODE_BOXED: + { + GIdlNodeBoxed *boxed = (GIdlNodeBoxed *)node; + boxed->members = + g_list_insert_sorted (boxed->members, member, + (GCompareFunc) g_idl_node_cmp); + break; + } + case G_IDL_NODE_STRUCT: + { + GIdlNodeStruct *struct_ = (GIdlNodeStruct *)node; + struct_->members = + g_list_insert_sorted (struct_->members, member, + (GCompareFunc) g_idl_node_cmp); + break; + } + case G_IDL_NODE_UNION: + { + GIdlNodeUnion *union_ = (GIdlNodeUnion *)node; + union_->members = + g_list_insert_sorted (union_->members, member, + (GCompareFunc) g_idl_node_cmp); + break; + } + default: + g_error ("Cannot add a member to unknown type tag type %d\n", + node->type); + break; + } +} + +const gchar * +g_idl_node_param_direction_string (GIdlNodeParam * node) +{ + if (node->out) + { + if (node->in) + return "in-out"; + else + return "out"; + } + return "in"; +} + +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; + + 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; + 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; + 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; + 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; + 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; + + *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; + + 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; + + 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; + default: + g_assert_not_reached (); + } + + 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/tools/girnode.h b/tools/girnode.h new file mode 100644 index 00000000..2e878890 --- /dev/null +++ b/tools/girnode.h @@ -0,0 +1,334 @@ +/* GObject introspection: Parsed GIR + * + * 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_IR_NODE_H__ +#define __G_IR_NODE_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _GIrNode GIrNode; +typedef struct _GIrNodeFunction GIrNodeFunction; +typedef struct _GIrNodeParam GIrNodeParam; +typedef struct _GIrNodeType GIrNodeType; +typedef struct _GIrNodeInterface GIrNodeInterface; +typedef struct _GIrNodeSignal GIrNodeSignal; +typedef struct _GIrNodeProperty GIrNodeProperty; +typedef struct _GIrNodeVFunc GIrNodeVFunc; +typedef struct _GIrNodeField GIrNodeField; +typedef struct _GIrNodeValue GIrNodeValue; +typedef struct _GIrNodeEnum GIrNodeEnum; +typedef struct _GIrNodeBoxed GIrNodeBoxed; +typedef struct _GIrNodeStruct GIrNodeStruct; +typedef struct _GIrNodeConstant GIrNodeConstant; +typedef struct _GIrNodeErrorDomain GIrNodeErrorDomain; +typedef struct _GIrNodeXRef GIrNodeXRef; +typedef struct _GIrNodeUnion GIrNodeUnion; + +typedef enum +{ + G_IR_NODE_INVALID, + G_IR_NODE_FUNCTION, + G_IR_NODE_CALLBACK, + G_IR_NODE_STRUCT, + G_IR_NODE_BOXED, + G_IR_NODE_ENUM, + G_IR_NODE_FLAGS, + G_IR_NODE_OBJECT, + G_IR_NODE_INTERFACE, + G_IR_NODE_CONSTANT, + G_IR_NODE_ERROR_DOMAIN, + G_IR_NODE_UNION, + G_IR_NODE_PARAM, + G_IR_NODE_TYPE, + G_IR_NODE_PROPERTY, + G_IR_NODE_SIGNAL, + G_IR_NODE_VALUE, + G_IR_NODE_VFUNC, + G_IR_NODE_FIELD, + G_IR_NODE_XREF +} GIrNodeTypeId; + +struct _GIrNode +{ + GIrNodeTypeId type; + gchar *name; +}; + +struct _GIrNodeXRef +{ + GIrNode node; + + gchar *namespace; +}; + +struct _GIrNodeFunction +{ + GIrNode node; + + gboolean deprecated; + + gboolean is_method; + gboolean is_setter; + gboolean is_getter; + gboolean is_constructor; + gboolean wraps_vfunc; + + gchar *symbol; + + GIrNodeParam *result; + GList *parameters; +}; + +struct _GIrNodeType +{ + GIrNode 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; + + GIrNodeType *parameter_type1; + GIrNodeType *parameter_type2; + + gchar *interface; + gchar **errors; +}; + +struct _GIrNodeParam +{ + GIrNode node; + + gboolean in; + gboolean out; + gboolean dipper; + gboolean optional; + gboolean retval; + gboolean null_ok; + gboolean transfer; + gboolean shallow_transfer; + + GIrNodeType *type; +}; + +struct _GIrNodeProperty +{ + GIrNode node; + + gboolean deprecated; + + gchar *name; + gboolean readable; + gboolean writable; + gboolean construct; + gboolean construct_only; + + GIrNodeType *type; +}; + +struct _GIrNodeSignal +{ + GIrNode 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; + GIrNodeParam *result; +}; + +struct _GIrNodeVFunc +{ + GIrNode node; + + gboolean must_chain_up; + gboolean must_be_implemented; + gboolean must_not_be_implemented; + gboolean is_class_closure; + + GList *parameters; + GIrNodeParam *result; + + gint offset; +}; + +struct _GIrNodeField +{ + GIrNode node; + + gboolean readable; + gboolean writable; + gint bits; + gint offset; + + GIrNodeType *type; +}; + +struct _GIrNodeInterface +{ + GIrNode node; + + gboolean deprecated; + + gchar *gtype_name; + gchar *gtype_init; + + gchar *parent; + + GList *interfaces; + GList *prerequisites; + + GList *members; +}; + +struct _GIrNodeValue +{ + GIrNode node; + + gboolean deprecated; + + guint32 value; +}; + +struct _GIrNodeConstant +{ + GIrNode node; + + gboolean deprecated; + + GIrNodeType *type; + + gchar *value; +}; + +struct _GIrNodeEnum +{ + GIrNode node; + + gboolean deprecated; + + gchar *gtype_name; + gchar *gtype_init; + + GList *values; +}; + +struct _GIrNodeBoxed +{ + GIrNode node; + + gboolean deprecated; + + gchar *gtype_name; + gchar *gtype_init; + + GList *members; +}; + +struct _GIrNodeStruct +{ + GIrNode node; + + gboolean deprecated; + + GList *members; +}; + +struct _GIrNodeUnion +{ + GIrNode node; + + gboolean deprecated; + + GList *members; + GList *discriminators; + + gchar *gtype_name; + gchar *gtype_init; + + gint discriminator_offset; + GIrNodeType *discriminator_type; +}; + + +struct _GIrNodeErrorDomain +{ + GIrNode node; + + gboolean deprecated; + + gchar *name; + gchar *getquark; + gchar *codes; +}; + + +GIrNode * g_ir_node_new (GIrNodeTypeId type); +void g_ir_node_free (GIrNode *node); +guint32 g_ir_node_get_size (GIrNode *node); +guint32 g_ir_node_get_full_size (GIrNode *node); +void g_ir_node_build_metadata (GIrNode *node, + GIdlModule *module, + GList *modules, + GHashTable *strings, + GHashTable *types, + guchar *data, + guint32 *offset, + guint32 *offset2); +int g_ir_node_cmp (GIrNode *node, + GIrNode *other); +gboolean g_ir_node_can_have_member (GIrNode *node); +void g_ir_node_add_member (GIrNode *node, + GIrNodeFunction *member); +guint32 write_string (const gchar *str, + GHashTable *strings, + guchar *data, + guint32 *offset); + +const gchar * g_ir_node_param_direction_string (GIrNodeParam * node); + +G_END_DECLS + +#endif /* __G_IR_NODE_H__ */ diff --git a/tools/girparser.c b/tools/girparser.c new file mode 100644 index 00000000..a60fd223 --- /dev/null +++ b/tools/girparser.c @@ -0,0 +1,2056 @@ +/* GObject introspection: A parser for the XML GIR format + * + * Copyright (C) 2008 Philip Van Hoof + * + * 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 +#include +#include + +#include +#include "gidlmodule.h" +#include "gidlnode.h" +#include "gtypelib.h" + +typedef enum +{ + STATE_START, + STATE_END, + STATE_REPOSITORY, + STATE_NAMESPACE, + STATE_ENUM, + STATE_BITFIELD, + STATE_FUNCTION, + STATE_PARAMETERS, + STATE_OBJECT, + STATE_INTERFACE, + STATE_IMPLEMENTS, + STATE_REQUIRES, + 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 }, + { "bool", TYPE_TAG_BOOLEAN, 0 }, + { "gboolean", TYPE_TAG_BOOLEAN, 0 }, +#if 0 + { "char", TYPE_TAG_INT8, 0 }, + { "gchar", TYPE_TAG_INT8, 0 }, + { "guchar", TYPE_TAG_UINT8, 0 }, +#endif + { "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 ("glib:type-name", attribute_names, attribute_values); + typeinit = find_attribute ("glib: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, "glib:type-name"); + else if (typeinit == NULL) + MISSING_ATTRIBUTE (error, element_name, "glib: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 ("c:identifier", 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, "c:identifier"); + 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; + default: + g_assert_not_reached (); + } + + 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; + default: + g_assert_not_reached (); + } + } + + 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; + default: + g_assert_not_reached (); + } + } + 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 ("glib:type-name", attribute_names, attribute_values); + typeinit = find_attribute ("glib: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 ("glib:type-name", attribute_names, attribute_values); + typeinit = find_attribute ("glib: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, "glib:type-name"); + else if (typeinit == NULL) + MISSING_ATTRIBUTE (error, element_name, "glib: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_class (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + ParseContext *ctx, + GError **error) +{ + if (strcmp (element_name, "class") == 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 ("glib:type-name", attribute_names, attribute_values); + typeinit = find_attribute ("glib: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, "glib:type-name"); + else if (typeinit == NULL) + MISSING_ATTRIBUTE (error, element_name, "glib: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; + default: + g_assert_not_reached (); + } + } + + 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, "glib: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 ("glib:type-name", attribute_names, attribute_values); + typeinit = find_attribute ("glib: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 line_number, char_number; + + switch (element_name[0]) + { + case 'r': + if (strcmp (element_name, "repository") == 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_NAMESPACE; + + 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, *shared_library; + + name = find_attribute ("name", attribute_names, attribute_values); + shared_library = find_attribute ("shared-library", attribute_names, attribute_values); + + if (name == NULL) + MISSING_ATTRIBUTE (error, element_name, "name"); + else + { + ctx->current_module = g_idl_module_new (name, shared_library); + ctx->modules = g_list_append (ctx->modules, ctx->current_module); + + ctx->state = STATE_NAMESPACE; + } + + goto out; + } + break; + + case 'c': + if (start_class (context, element_name, + attribute_names, attribute_values, + ctx, error)) + goto out; + else if (strcmp (element_name, "class") == 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_REPOSITORY: + ctx->state = STATE_END; + break; + + case STATE_NAMESPACE: + if (strcmp (element_name, "namespace") == 0) + { + ctx->current_module = NULL; + ctx->state = STATE_NAMESPACE; + } + 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, "class") == 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: + if (strcmp (element_name, "requires") == 0) + 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_ir_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_ir_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_ir_parse_string (buffer, length, error); + + g_free (buffer); + + return modules; +} + + diff --git a/tools/girparser.h b/tools/girparser.h new file mode 100644 index 00000000..ed9e6ceb --- /dev/null +++ b/tools/girparser.h @@ -0,0 +1,38 @@ +/* GObject introspection: A parser for the XML GIR 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_GIR_PARSER_H__ +#define __G_GIR_PARSER_H__ + +#include + +G_BEGIN_DECLS + + +GList *g_ir_parse_string (const gchar *buffer, + gssize length, + GError **error); +GList *g_ir_parse_file (const gchar *filename, + GError **error); + + +G_END_DECLS + +#endif /* __G_GIR_PARSER_H__ */ diff --git a/tools/girwriter.c b/tools/girwriter.c new file mode 100644 index 00000000..c99d1deb --- /dev/null +++ b/tools/girwriter.c @@ -0,0 +1,529 @@ +/* GObject introspection: gen-introspect + * + * Copyright (C) 2007 Jürg Billeter + * Copyright (C) 2007 Johan Dahlin + * + * 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.1 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. + * + * Author: + * Jürg Billeter + */ + +#include +#include +#include "scanner.h" +#include "gidlnode.h" + +typedef struct { + int indent; + FILE *output; +} GIdlWriter; + +static void node_generate (GIdlWriter * writer, GIdlNode * node); + +static void +g_writer_write_inline (GIdlWriter * writer, const char *s) +{ + fprintf (writer->output, "%s", s); +} + +static void +g_writer_write (GIdlWriter * writer, const char *s) +{ + int i; + for (i = 0; i < writer->indent; i++) + { + fprintf (writer->output, "\t"); + } + + g_writer_write_inline (writer, s); +} + +static void +g_writer_write_indent (GIdlWriter * writer, const char *s) +{ + g_writer_write (writer, s); + writer->indent++; +} + +static void +g_writer_write_unindent (GIdlWriter * writer, const char *s) +{ + writer->indent--; + g_writer_write (writer, s); +} + +static void +field_generate (GIdlWriter * writer, GIdlNodeField * node) +{ + char *markup = + g_markup_printf_escaped ("\n", + node->node.name, node->type->unparsed); + g_writer_write (writer, markup); + g_free (markup); +} + +static void +value_generate (GIdlWriter * writer, GIdlNodeValue * node) +{ + char *markup = + g_markup_printf_escaped ("\n", + node->node.name, node->value); + g_writer_write (writer, markup); + g_free (markup); +} + +static void +constant_generate (GIdlWriter * writer, GIdlNodeConstant * node) +{ + char *markup = + g_markup_printf_escaped + ("\n", node->node.name, + node->type->unparsed, node->value); + g_writer_write (writer, markup); + g_free (markup); +} + +static void +property_generate (GIdlWriter * writer, GIdlNodeProperty * node) +{ + char *markup = + g_markup_printf_escaped ("\n", + node->node.name, + node->type->unparsed, + node->readable ? "1" : "0", + node->writable ? "1" : "0", + node->construct ? "1" : "0", + node->construct_only ? "1" : "0"); + g_writer_write (writer, markup); + g_free (markup); +} + +static void +function_generate (GIdlWriter * writer, GIdlNodeFunction * node) +{ + const char *tag_name; + GString *markup_s; + gchar *markup; + + if (node->node.type == G_IDL_NODE_CALLBACK) + tag_name = "callback"; + else if (node->is_constructor) + tag_name = "constructor"; + else if (node->is_method) + tag_name = "method"; + else + tag_name = "function"; + + markup_s = g_string_new ("<"); + g_string_append_printf (markup_s, + "%s name=\"%s\"", + tag_name, node->node.name); + + if (node->node.type != G_IDL_NODE_CALLBACK) + g_string_append_printf (markup_s, + g_markup_printf_escaped (" symbol=\"%s\"", node->symbol)); + + if (node->deprecated) + g_string_append_printf (markup_s, " deprecated=\"1\""); + + g_string_append (markup_s, ">\n"); + + g_writer_write_indent (writer, markup_s->str); + g_string_free (markup_s, TRUE); + + markup_s = + g_string_new (g_markup_printf_escaped ("result->type->unparsed)); + + if (node->result->transfer) + g_string_append (markup_s, g_markup_printf_escaped (" transfer=\"full\"/>\n")); + else + g_string_append (markup_s, "/>\n"); + + g_writer_write (writer, markup_s->str); + g_string_free (markup_s, TRUE); + + if (node->parameters != NULL) + { + GList *l; + g_writer_write_indent (writer, "\n"); + for (l = node->parameters; l != NULL; l = l->next) + { + GIdlNodeParam *param = l->data; + const gchar *direction = g_idl_node_param_direction_string (param); + + markup_s = g_string_new ("node.name); + + g_string_append (markup_s, + g_markup_printf_escaped (" type=\"%s\"", + param->type->unparsed)); + + if (param->transfer) + g_string_append (markup_s, + g_markup_printf_escaped (" transfer=\"full\"")); + + if (param->null_ok) + g_string_append (markup_s, + g_markup_printf_escaped (" null-ok=\"1\"")); + + if (strcmp (direction, "in") != 0) + g_string_append (markup_s, + g_markup_printf_escaped (" direction=\"%s\"", + direction)); + + g_string_append (markup_s, "/>\n"); + + g_writer_write (writer, markup_s->str); + g_string_free (markup_s, TRUE); + } + g_writer_write_unindent (writer, "\n"); + } + markup = g_strdup_printf ("\n", tag_name); + g_writer_write_unindent (writer, markup); + g_free (markup); +} + +static void +vfunc_generate (GIdlWriter * writer, GIdlNodeVFunc * node) +{ + char *markup = + g_markup_printf_escaped ("\n", node->node.name); + g_writer_write_indent (writer, markup); + g_free (markup); + markup = + g_markup_printf_escaped ("\n", + node->result->type->unparsed); + g_writer_write (writer, markup); + g_free (markup); + if (node->parameters != NULL) + { + GList *l; + g_writer_write_indent (writer, "\n"); + for (l = node->parameters; l != NULL; l = l->next) + { + GIdlNodeParam *param = l->data; + markup = + g_markup_printf_escaped ("\n", + param->node.name, param->type->unparsed); + g_writer_write (writer, markup); + g_free (markup); + } + g_writer_write_unindent (writer, "\n"); + } + g_writer_write_unindent (writer, "\n"); +} + +static void +signal_generate (GIdlWriter * writer, GIdlNodeSignal * node) +{ + char *markup; + const char *when = "LAST"; + if (node->run_first) + { + when = "FIRST"; + } + else if (node->run_cleanup) + { + when = "CLEANUP"; + } + markup = + g_markup_printf_escaped ("\n", + node->node.name, when); + g_writer_write_indent (writer, markup); + g_free (markup); + markup = + g_markup_printf_escaped ("\n", + node->result->type->unparsed); + g_writer_write (writer, markup); + g_free (markup); + if (node->parameters != NULL) + { + GList *l; + g_writer_write_indent (writer, "\n"); + for (l = node->parameters; l != NULL; l = l->next) + { + GIdlNodeParam *param = l->data; + markup = + g_markup_printf_escaped ("\n", + param->node.name, param->type->unparsed); + g_writer_write (writer, markup); + g_free (markup); + } + g_writer_write_unindent (writer, "\n"); + } + g_writer_write_unindent (writer, "\n"); +} + +static void +interface_generate (GIdlWriter * writer, GIdlNodeInterface * node) +{ + GList *l; + char *markup; + if (node->node.type == G_IDL_NODE_OBJECT) + { + markup = + g_markup_printf_escaped ("\n", + node->node.name, + node->parent, + node->gtype_name, + node->gtype_init); + } + else if (node->node.type == G_IDL_NODE_INTERFACE) + { + markup = + g_markup_printf_escaped + ("\n", + node->node.name, node->gtype_name, node->gtype_init); + } + + g_writer_write_indent (writer, markup); + g_free (markup); + if (node->node.type == G_IDL_NODE_OBJECT && node->interfaces != NULL) + { + GList *l; + g_writer_write_indent (writer, "\n"); + for (l = node->interfaces; l != NULL; l = l->next) + { + markup = + g_markup_printf_escaped ("\n", + (char *) l->data); + g_writer_write (writer, markup); + g_free (markup); + } + g_writer_write_unindent (writer, "\n"); + } + else if (node->node.type == G_IDL_NODE_INTERFACE + && node->prerequisites != NULL) + { + GList *l; + g_writer_write_indent (writer, "\n"); + for (l = node->prerequisites; l != NULL; l = l->next) + { + markup = + g_markup_printf_escaped ("\n", + (char *) l->data); + g_writer_write (writer, markup); + g_free (markup); + } + g_writer_write_unindent (writer, "\n"); + } + + for (l = node->members; l != NULL; l = l->next) + { + node_generate (writer, l->data); + } + + if (node->node.type == G_IDL_NODE_OBJECT) + { + g_writer_write_unindent (writer, "\n"); + } + else if (node->node.type == G_IDL_NODE_INTERFACE) + { + g_writer_write_unindent (writer, "\n"); + } +} + +static void +struct_generate (GIdlWriter * writer, GIdlNodeStruct * node) +{ + GList *l; + char *markup = + g_markup_printf_escaped ("\n", node->node.name); + g_writer_write_indent (writer, markup); + g_free (markup); + for (l = node->members; l != NULL; l = l->next) + { + node_generate (writer, l->data); + } + g_writer_write_unindent (writer, "\n"); +} + +static void +union_generate (GIdlWriter * writer, GIdlNodeUnion * node) +{ + GList *l; + char *markup = + g_markup_printf_escaped ("\n", node->node.name); + g_writer_write_indent (writer, markup); + g_free (markup); + for (l = node->members; l != NULL; l = l->next) + { + node_generate (writer, l->data); + } + g_writer_write_unindent (writer, "\n"); +} + +static void +boxed_generate (GIdlWriter * writer, GIdlNodeBoxed * node) +{ + GList *l; + char *markup = + g_markup_printf_escaped + ("\n", + node->node.name, node->gtype_name, node->gtype_init); + g_writer_write_indent (writer, markup); + g_free (markup); + for (l = node->members; l != NULL; l = l->next) + { + node_generate (writer, l->data); + } + g_writer_write_unindent (writer, "\n"); +} + +static void +enum_generate (GIdlWriter * writer, GIdlNodeEnum * node) +{ + GList *l; + GString *markup_s; + char *markup; + const char *tag_name = NULL; + + if (node->node.type == G_IDL_NODE_ENUM) + { + tag_name = "enum"; + } + else if (node->node.type == G_IDL_NODE_FLAGS) + { + tag_name = "flags"; + } + + markup_s = g_string_new ("<"); + g_string_append_printf (markup_s, + "%s name=\"%s\"", + tag_name, node->node.name); + + if (node->gtype_name != NULL) + g_string_append_printf (markup_s, + g_markup_printf_escaped (" type-name=\"%s\"", node->gtype_name)); + + if (node->gtype_init != NULL) + g_string_append_printf (markup_s, + g_markup_printf_escaped (" get-type=\"%s\"", node->gtype_init)); + + if (node->deprecated) + g_string_append_printf (markup_s, " deprecated=\"1\""); + + g_string_append (markup_s, ">\n"); + + g_writer_write_indent (writer, markup_s->str); + g_string_free (markup_s, TRUE); + + for (l = node->values; l != NULL; l = l->next) + { + node_generate (writer, l->data); + } + + markup = g_strdup_printf ("\n", tag_name); + g_writer_write_unindent (writer, markup); + g_free (markup); +} + +static void +node_generate (GIdlWriter * writer, GIdlNode * node) +{ + switch (node->type) + { + case G_IDL_NODE_FUNCTION: + case G_IDL_NODE_CALLBACK: + function_generate (writer, (GIdlNodeFunction *) node); + break; + case G_IDL_NODE_VFUNC: + vfunc_generate (writer, (GIdlNodeVFunc *) node); + break; + case G_IDL_NODE_OBJECT: + case G_IDL_NODE_INTERFACE: + interface_generate (writer, (GIdlNodeInterface *) node); + break; + case G_IDL_NODE_STRUCT: + struct_generate (writer, (GIdlNodeStruct *) node); + break; + case G_IDL_NODE_UNION: + union_generate (writer, (GIdlNodeUnion *) node); + break; + case G_IDL_NODE_BOXED: + boxed_generate (writer, (GIdlNodeBoxed *) node); + break; + case G_IDL_NODE_ENUM: + case G_IDL_NODE_FLAGS: + enum_generate (writer, (GIdlNodeEnum *) node); + break; + case G_IDL_NODE_PROPERTY: + property_generate (writer, (GIdlNodeProperty *) node); + break; + case G_IDL_NODE_FIELD: + field_generate (writer, (GIdlNodeField *) node); + break; + case G_IDL_NODE_SIGNAL: + signal_generate (writer, (GIdlNodeSignal *) node); + break; + case G_IDL_NODE_VALUE: + value_generate (writer, (GIdlNodeValue *) node); + break; + case G_IDL_NODE_CONSTANT: + constant_generate (writer, (GIdlNodeConstant *) node); + break; + default: + g_assert_not_reached (); + } +} + +static void +g_writer_write_module (GIdlWriter * writer, GIdlModule * module) +{ + GList *l; + char *markup = + g_markup_printf_escaped ("\n", module->name); + g_writer_write_indent (writer, markup); + g_free (markup); + for (l = module->entries; l != NULL; l = l->next) + { + node_generate (writer, l->data); + } + g_writer_write_unindent (writer, "\n"); +} + +void +g_idl_writer_save_file (GIdlModule *module, + const gchar *filename) +{ + GIdlWriter *writer; + + writer = g_new0 (GIdlWriter, 1); + + if (!filename) + writer->output = stdout; + else + writer->output = fopen (filename, "w"); + + g_writer_write (writer, "\n"); + g_writer_write_indent (writer, "\n"); + g_writer_write_module (writer, module); + g_writer_write_unindent (writer, "\n"); + + if (filename) + fclose (writer->output); +} diff --git a/tools/girwriter.h b/tools/girwriter.h new file mode 100644 index 00000000..5d41a0c6 --- /dev/null +++ b/tools/girwriter.h @@ -0,0 +1,26 @@ +/* GObject introspection: IDL writer + * + * Copyright (C) 2007 Johan Dahlin + * + * 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_WRITER_H__ +#define __G_IDL_WRITER_H__ + +void g_idl_writer_save_file (GIdlModule *module, const gchar *filename); + +#endif /* __G_IDL_WRITER_H__ */ -- cgit v1.2.1