summaryrefslogtreecommitdiff
path: root/gobject-introspection
diff options
context:
space:
mode:
authorJuerg Billeter <j@bitron.ch>2008-01-11 21:44:01 +0000
committerJürg Billeter <juergbi@src.gnome.org>2008-01-11 21:44:01 +0000
commit2549f2b773a9d91a8c11d947019ce81d822207c9 (patch)
tree69d140e8e49323d93e627442873ad48fe1ca8be2 /gobject-introspection
parent93b91d12979c0343b1240f06be989b1e44a2ba0f (diff)
downloadvala-2549f2b773a9d91a8c11d947019ce81d822207c9.tar.gz
update from gobject-introspection SVN, fixes bug 505920
2008-01-11 Juerg Billeter <j@bitron.ch> * gobject-introspection/: update from gobject-introspection SVN, fixes bug 505920 * vapigen/vala-gen-introspect/vala-gen-introspect.in: fix to work with updated gobject-introspection svn path=/trunk/; revision=829
Diffstat (limited to 'gobject-introspection')
-rw-r--r--gobject-introspection/Makefile.am15
-rw-r--r--gobject-introspection/gen-introspect.c1372
-rw-r--r--gobject-introspection/gen-introspect.h157
-rw-r--r--gobject-introspection/gidlmodule.c23
-rw-r--r--gobject-introspection/gidlmodule.h11
-rw-r--r--gobject-introspection/gidlparser.c13
-rw-r--r--gobject-introspection/gidlwriter.c483
-rw-r--r--gobject-introspection/gidlwriter.h26
-rw-r--r--gobject-introspection/girepository.h452
-rw-r--r--gobject-introspection/gmetadata.c1876
-rw-r--r--gobject-introspection/gmetadata.h24
-rw-r--r--gobject-introspection/scanner.c1824
-rw-r--r--gobject-introspection/scanner.h167
-rw-r--r--gobject-introspection/scannerlexer.l (renamed from gobject-introspection/clexer.l)118
-rw-r--r--gobject-introspection/scannerparser.y (renamed from gobject-introspection/cparser.y)230
15 files changed, 5160 insertions, 1631 deletions
diff --git a/gobject-introspection/Makefile.am b/gobject-introspection/Makefile.am
index 47e771fe8..4ec02752e 100644
--- a/gobject-introspection/Makefile.am
+++ b/gobject-introspection/Makefile.am
@@ -15,24 +15,29 @@ libgidl_la_SOURCES = \
gidlnode.h \
gidlparser.c \
gidlparser.h \
+ girepository.h \
+ gmetadata.c \
gmetadata.h \
$(NULL)
libgidl_la_LIBADD = \
$(GLIB_LIBS) \
+ $(GMODULE_LIBS) \
$(NULL)
pkglibexecdir = $(libdir)/vala
pkglibexec_PROGRAMS = gen-introspect
-BUILT_SOURCES = cparser.h
+BUILT_SOURCES = scannerparser.h
AM_YFLAGS = -d
gen_introspect_SOURCES = \
- clexer.l \
- cparser.y \
- gen-introspect.c \
- gen-introspect.h \
+ gidlwriter.c \
+ gidlwriter.h \
+ scanner.c \
+ scanner.h \
+ scannerlexer.l \
+ scannerparser.y \
$(NULL)
gen_introspect_LDADD = \
diff --git a/gobject-introspection/gen-introspect.c b/gobject-introspection/gen-introspect.c
deleted file mode 100644
index edd64ab5d..000000000
--- a/gobject-introspection/gen-introspect.c
+++ /dev/null
@@ -1,1372 +0,0 @@
-/* GObject introspection: gen-introspect
- *
- * Copyright (C) 2007 Jürg Billeter
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.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 <j@bitron.ch>
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <glib-object.h>
-#include <gmodule.h>
-#include "gen-introspect.h"
-#include "gidlmodule.h"
-#include "gidlnode.h"
-
-typedef GType (*TypeFunction) (void);
-
-static void node_generate (GIGenerator *igenerator, GIdlNode *node);
-static void g_igenerator_parse_macros (GIGenerator *igenerator);
-
-static int g_idl_node_cmp (GIdlNode *a, GIdlNode *b)
-{
- if (a->type < b->type) {
- return -1;
- } else if (a->type > b->type) {
- return 1;
- } else {
- return strcmp (a->name, b->name);
- }
-}
-
-GIGenerator *g_igenerator_new (void)
-{
- GIGenerator *igenerator = g_new0 (GIGenerator, 1);
- igenerator->namespace = "";
- igenerator->lower_case_namespace = g_strdup ("");
- igenerator->typedef_table = g_hash_table_new (g_str_hash, g_str_equal);
- igenerator->struct_or_union_or_enum_table = g_hash_table_new (g_str_hash, g_str_equal);
-
- igenerator->type_map = g_hash_table_new (g_str_hash, g_str_equal);
- igenerator->type_by_lower_case_prefix = g_hash_table_new (g_str_hash, g_str_equal);
-
- the_igenerator = igenerator;
-
- return igenerator;
-}
-
-static void g_igenerator_write_inline (GIGenerator *igenerator, const char *s)
-{
- fprintf (stdout, "%s", s);
-}
-
-static void g_igenerator_write (GIGenerator *igenerator, const char *s)
-{
- int i;
- for (i = 0; i < igenerator->indent; i++) {
- fprintf (stdout, "\t");
- }
-
- g_igenerator_write_inline (igenerator, s);
-}
-
-static void g_igenerator_write_indent (GIGenerator *igenerator, const char *s)
-{
- g_igenerator_write (igenerator, s);
- igenerator->indent++;
-}
-
-static void g_igenerator_write_unindent (GIGenerator *igenerator, const char *s)
-{
- igenerator->indent--;
- g_igenerator_write (igenerator, s);
-}
-
-static void field_generate (GIGenerator *igenerator, GIdlNodeField *node)
-{
- char *markup = g_markup_printf_escaped ("<field name=\"%s\" type=\"%s\"/>\n", node->node.name, node->type->unparsed);
- g_igenerator_write (igenerator, markup);
- g_free (markup);
-}
-
-static void value_generate (GIGenerator *igenerator, GIdlNodeValue *node)
-{
- char *markup = g_markup_printf_escaped ("<member name=\"%s\" value=\"%d\"/>\n", node->node.name, node->value);
- g_igenerator_write (igenerator, markup);
- g_free (markup);
-}
-
-static void constant_generate (GIGenerator *igenerator, GIdlNodeConstant *node)
-{
- char *markup = g_markup_printf_escaped ("<constant name=\"%s\" type=\"%s\" value=\"%s\"/>\n", node->node.name, node->type->unparsed, node->value);
- g_igenerator_write (igenerator, markup);
- g_free (markup);
-}
-
-static void property_generate (GIGenerator *igenerator, GIdlNodeProperty *node)
-{
- char *markup = g_markup_printf_escaped ("<property name=\"%s\" type=\"%s\" readable=\"%s\" writable=\"%s\" construct=\"%s\" construct-only=\"%s\"/>\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_igenerator_write (igenerator, markup);
- g_free (markup);
-}
-
-static void function_generate (GIGenerator *igenerator, GIdlNodeFunction *node)
-{
- char *markup;
- const char *tag_name;
- if (node->node.type == G_IDL_NODE_CALLBACK) {
- tag_name = "callback";
- markup = g_markup_printf_escaped ("<callback name=\"%s\">\n", node->node.name);
- } else if (node->is_constructor) {
- tag_name = "constructor";
- markup = g_markup_printf_escaped ("<constructor name=\"%s\" symbol=\"%s\">\n", node->node.name, node->symbol);
- } else if (node->is_method) {
- tag_name = "method";
- markup = g_markup_printf_escaped ("<method name=\"%s\" symbol=\"%s\">\n", node->node.name, node->symbol);
- } else {
- tag_name = "function";
- markup = g_markup_printf_escaped ("<function name=\"%s\" symbol=\"%s\">\n", node->node.name, node->symbol);
- }
-
- g_igenerator_write_indent (igenerator, markup);
- g_free (markup);
- markup = g_markup_printf_escaped ("<return-type type=\"%s\"/>\n", node->result->type->unparsed);
- g_igenerator_write (igenerator, markup);
- g_free (markup);
- if (node->parameters != NULL) {
- GList *l;
- g_igenerator_write_indent (igenerator, "<parameters>\n");
- for (l = node->parameters; l != NULL; l = l->next) {
- GIdlNodeParam *param = l->data;
- markup = g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n", param->node.name, param->type->unparsed);
- g_igenerator_write (igenerator, markup);
- g_free (markup);
- }
- g_igenerator_write_unindent (igenerator, "</parameters>\n");
- }
- markup = g_strdup_printf ("</%s>\n", tag_name);
- g_igenerator_write_unindent (igenerator, markup);
- g_free (markup);
-}
-
-static void vfunc_generate (GIGenerator *igenerator, GIdlNodeVFunc *node)
-{
- char *markup = g_markup_printf_escaped ("<vfunc name=\"%s\">\n", node->node.name);
- g_igenerator_write_indent (igenerator, markup);
- g_free (markup);
- markup = g_markup_printf_escaped ("<return-type type=\"%s\"/>\n", node->result->type->unparsed);
- g_igenerator_write (igenerator, markup);
- g_free (markup);
- if (node->parameters != NULL) {
- GList *l;
- g_igenerator_write_indent (igenerator, "<parameters>\n");
- for (l = node->parameters; l != NULL; l = l->next) {
- GIdlNodeParam *param = l->data;
- markup = g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n", param->node.name, param->type->unparsed);
- g_igenerator_write (igenerator, markup);
- g_free (markup);
- }
- g_igenerator_write_unindent (igenerator, "</parameters>\n");
- }
- g_igenerator_write_unindent (igenerator, "</vfunc>\n");
-}
-
-static void signal_generate (GIGenerator *igenerator, 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 ("<signal name=\"%s\" when=\"%s\">\n", node->node.name, when);
- g_igenerator_write_indent (igenerator, markup);
- g_free (markup);
- markup = g_markup_printf_escaped ("<return-type type=\"%s\"/>\n", node->result->type->unparsed);
- g_igenerator_write (igenerator, markup);
- g_free (markup);
- if (node->parameters != NULL) {
- GList *l;
- g_igenerator_write_indent (igenerator, "<parameters>\n");
- for (l = node->parameters; l != NULL; l = l->next) {
- GIdlNodeParam *param = l->data;
- markup = g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n", param->node.name, param->type->unparsed);
- g_igenerator_write (igenerator, markup);
- g_free (markup);
- }
- g_igenerator_write_unindent (igenerator, "</parameters>\n");
- }
- g_igenerator_write_unindent (igenerator, "</signal>\n");
-}
-
-static void interface_generate (GIGenerator *igenerator, GIdlNodeInterface *node)
-{
- GList *l;
- char *markup;
- if (node->node.type == G_IDL_NODE_OBJECT) {
- markup = g_markup_printf_escaped ("<object name=\"%s\" parent=\"%s\" type-name=\"%s\" get-type=\"%s\">\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 ("<interface name=\"%s\" type-name=\"%s\" get-type=\"%s\">\n", node->node.name, node->gtype_name, node->gtype_init);
- }
-
- g_igenerator_write_indent (igenerator, markup);
- g_free (markup);
- if (node->node.type == G_IDL_NODE_OBJECT && node->interfaces != NULL) {
- GList *l;
- g_igenerator_write_indent (igenerator, "<implements>\n");
- for (l = node->interfaces; l != NULL; l = l->next) {
- markup = g_markup_printf_escaped ("<interface name=\"%s\"/>\n", (char *) l->data);
- g_igenerator_write (igenerator, markup);
- g_free (markup);
- }
- g_igenerator_write_unindent (igenerator, "</implements>\n");
- } else if (node->node.type == G_IDL_NODE_INTERFACE && node->prerequisites != NULL) {
- GList *l;
- g_igenerator_write_indent (igenerator, "<requires>\n");
- for (l = node->prerequisites; l != NULL; l = l->next) {
- markup = g_markup_printf_escaped ("<interface name=\"%s\"/>\n", (char *) l->data);
- g_igenerator_write (igenerator, markup);
- g_free (markup);
- }
- g_igenerator_write_unindent (igenerator, "</requires>\n");
- }
-
- for (l = node->members; l != NULL; l = l->next) {
- node_generate (igenerator, l->data);
- }
-
- if (node->node.type == G_IDL_NODE_OBJECT) {
- g_igenerator_write_unindent (igenerator, "</object>\n");
- } else if (node->node.type == G_IDL_NODE_INTERFACE) {
- g_igenerator_write_unindent (igenerator, "</interface>\n");
- }
-}
-
-static void struct_generate (GIGenerator *igenerator, GIdlNodeStruct *node)
-{
- GList *l;
- char *markup = g_markup_printf_escaped ("<struct name=\"%s\">\n", node->node.name);
- g_igenerator_write_indent (igenerator, markup);
- g_free (markup);
- for (l = node->members; l != NULL; l = l->next) {
- node_generate (igenerator, l->data);
- }
- g_igenerator_write_unindent (igenerator, "</struct>\n");
-}
-
-static void union_generate (GIGenerator *igenerator, GIdlNodeUnion *node)
-{
- GList *l;
- char *markup = g_markup_printf_escaped ("<union name=\"%s\">\n", node->node.name);
- g_igenerator_write_indent (igenerator, markup);
- g_free (markup);
- for (l = node->members; l != NULL; l = l->next) {
- node_generate (igenerator, l->data);
- }
- g_igenerator_write_unindent (igenerator, "</union>\n");
-}
-
-static void boxed_generate (GIGenerator *igenerator, GIdlNodeBoxed *node)
-{
- GList *l;
- char *markup = g_markup_printf_escaped ("<boxed name=\"%s\" type-name=\"%s\" get-type=\"%s\">\n", node->node.name, node->gtype_name, node->gtype_init);
- g_igenerator_write_indent (igenerator, markup);
- g_free (markup);
- for (l = node->members; l != NULL; l = l->next) {
- node_generate (igenerator, l->data);
- }
- g_igenerator_write_unindent (igenerator, "</boxed>\n");
-}
-
-static void enum_generate (GIGenerator *igenerator, GIdlNodeEnum *node)
-{
- GList *l;
- 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 = g_markup_printf_escaped ("<%s name=\"%s\">\n", tag_name, node->node.name);
- g_igenerator_write_indent (igenerator, markup);
- g_free (markup);
-
- for (l = node->values; l != NULL; l = l->next) {
- node_generate (igenerator, l->data);
- }
-
- markup = g_strdup_printf ("</%s>\n", tag_name);
- g_igenerator_write_unindent (igenerator, markup);
- g_free (markup);
-}
-
-static void node_generate (GIGenerator *igenerator, GIdlNode *node)
-{
- switch (node->type) {
- case G_IDL_NODE_FUNCTION:
- case G_IDL_NODE_CALLBACK:
- function_generate (igenerator, (GIdlNodeFunction *) node);
- break;
- case G_IDL_NODE_VFUNC:
- vfunc_generate (igenerator, (GIdlNodeVFunc *) node);
- break;
- case G_IDL_NODE_OBJECT:
- case G_IDL_NODE_INTERFACE:
- interface_generate (igenerator, (GIdlNodeInterface *) node);
- break;
- case G_IDL_NODE_STRUCT:
- struct_generate (igenerator, (GIdlNodeStruct *) node);
- break;
- case G_IDL_NODE_UNION:
- union_generate (igenerator, (GIdlNodeUnion *) node);
- break;
- case G_IDL_NODE_BOXED:
- boxed_generate (igenerator, (GIdlNodeBoxed *) node);
- break;
- case G_IDL_NODE_ENUM:
- case G_IDL_NODE_FLAGS:
- enum_generate (igenerator, (GIdlNodeEnum *) node);
- break;
- case G_IDL_NODE_PROPERTY:
- property_generate (igenerator, (GIdlNodeProperty *) node);
- break;
- case G_IDL_NODE_FIELD:
- field_generate (igenerator, (GIdlNodeField *) node);
- break;
- case G_IDL_NODE_SIGNAL:
- signal_generate (igenerator, (GIdlNodeSignal *) node);
- break;
- case G_IDL_NODE_VALUE:
- value_generate (igenerator, (GIdlNodeValue *) node);
- break;
- case G_IDL_NODE_CONSTANT:
- constant_generate (igenerator, (GIdlNodeConstant *) node);
- break;
- default:
- g_assert_not_reached ();
- }
-}
-
-static void module_generate (GIGenerator *igenerator, GIdlModule *module)
-{
- GList *l;
- char *markup = g_markup_printf_escaped ("<namespace name=\"%s\">\n", module->name);
- g_igenerator_write_indent (igenerator, markup);
- g_free (markup);
- for (l = module->entries; l != NULL; l = l->next) {
- node_generate (igenerator, l->data);
- }
- g_igenerator_write_unindent (igenerator, "</namespace>\n");
-}
-
-static GIdlNodeType *get_type_from_type_id (GType type_id)
-{
- GIdlNodeType *gitype = (GIdlNodeType *) g_idl_node_new (G_IDL_NODE_TYPE);
-
- GType type_fundamental = g_type_fundamental (type_id);
-
- if (type_fundamental == G_TYPE_STRING) {
- gitype->unparsed = g_strdup ("char*");
- } else if (type_id == G_TYPE_STRV) {
- gitype->unparsed = g_strdup ("char*[]");
- } else if (type_fundamental == G_TYPE_INTERFACE || type_fundamental == G_TYPE_BOXED || type_fundamental == G_TYPE_OBJECT) {
- gitype->unparsed = g_strdup_printf ("%s*", g_type_name (type_id));
- } else if (type_fundamental == G_TYPE_PARAM) {
- gitype->unparsed = g_strdup ("GParamSpec*");
- } else {
- gitype->unparsed = g_strdup (g_type_name (type_id));
- }
-
- return gitype;
-}
-
-static char *str_replace (const char *str, const char *needle, const char *replacement)
-{
- char **strings = g_strsplit (str, needle, 0);
- char *result = g_strjoinv (replacement, strings);
- g_strfreev (strings);
- return result;
-}
-
-static void g_igenerator_process_properties (GIGenerator *igenerator, GIdlNodeInterface *ginode, GType type_id)
-{
- int i;
- guint n_properties;
- GParamSpec **properties;
-
- if (ginode->node.type == G_IDL_NODE_OBJECT) {
- GObjectClass *type_class = g_type_class_ref (type_id);
- properties = g_object_class_list_properties (type_class, &n_properties);
- } else if (ginode->node.type == G_IDL_NODE_INTERFACE) {
- GTypeInterface *iface = g_type_default_interface_ref (type_id);
- properties = g_object_interface_list_properties (iface, &n_properties);
- } else {
- g_assert_not_reached ();
- }
-
- for (i = 0; i < n_properties; i++) {
- /* ignore inherited properties */
- if (properties[i]->owner_type != type_id) {
- continue;
- }
- GIdlNodeProperty *giprop = (GIdlNodeProperty *) g_idl_node_new (G_IDL_NODE_PROPERTY);
- giprop->node.name = properties[i]->name;
- ginode->members = g_list_insert_sorted (ginode->members, giprop, (GCompareFunc) g_idl_node_cmp);
- giprop->type = get_type_from_type_id (properties[i]->value_type);
- giprop->readable = (properties[i]->flags & G_PARAM_READABLE) != 0;
- giprop->writable = (properties[i]->flags & G_PARAM_WRITABLE) != 0;
- giprop->construct = (properties[i]->flags & G_PARAM_CONSTRUCT) != 0;
- giprop->construct_only = (properties[i]->flags & G_PARAM_CONSTRUCT_ONLY) != 0;
- }
-}
-
-static void g_igenerator_process_signals (GIGenerator *igenerator, GIdlNodeInterface *ginode, GType type_id)
-{
- int i, j;
- guint n_signal_ids;
- guint *signal_ids = g_signal_list_ids (type_id, &n_signal_ids);
-
- for (i = 0; i < n_signal_ids; i++) {
- GSignalQuery signal_query;
- g_signal_query (signal_ids[i], &signal_query);
- GIdlNodeSignal *gisig = (GIdlNodeSignal *) g_idl_node_new (G_IDL_NODE_SIGNAL);
- gisig->node.name = g_strdup (signal_query.signal_name);
- ginode->members = g_list_insert_sorted (ginode->members, gisig, (GCompareFunc) g_idl_node_cmp);
-
- gisig->run_first = (signal_query.signal_flags & G_SIGNAL_RUN_FIRST) != 0;
- gisig->run_last = (signal_query.signal_flags & G_SIGNAL_RUN_LAST) != 0;
- gisig->run_cleanup = (signal_query.signal_flags & G_SIGNAL_RUN_CLEANUP) != 0;
-
- /* add sender parameter */
- GIdlNodeParam *giparam = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
- gisig->parameters = g_list_append (gisig->parameters, giparam);
- giparam->node.name = g_strdup ("object");
- giparam->type = get_type_from_type_id (type_id);
-
- for (j = 0; j < signal_query.n_params; j++) {
- giparam = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
- gisig->parameters = g_list_append (gisig->parameters, giparam);
- giparam->node.name = g_strdup_printf ("p%d", j);
- giparam->type = get_type_from_type_id (signal_query.param_types[j]);
- }
- gisig->result = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
- gisig->result->type = get_type_from_type_id (signal_query.return_type);
- }
-}
-
-static void g_igenerator_process_types (GIGenerator *igenerator)
-{
- int i;
- GList *lib_l;
-
- /* ensure to initialize GObject */
- g_type_class_ref (G_TYPE_OBJECT);
-
- for (lib_l = igenerator->libraries; lib_l != NULL; lib_l = lib_l->next) {
- GList *l;
- GModule *module = g_module_open (lib_l->data, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
- if (module == NULL) {
- g_critical ("Couldn't open module: %s", (char *) lib_l->data);
- continue;
- }
- for (l = igenerator->get_type_symbols; l != NULL; l = l->next) {
- char *get_type_symbol = l->data;
-
- if (get_type_symbol == NULL) {
- /* ignore already processed functions */
- continue;
- }
-
- TypeFunction type_fun;
- if (!g_module_symbol (module, get_type_symbol, (gpointer*) &type_fun)) {
- continue;
- }
-
- /* symbol found, ignore in future iterations */
- l->data = NULL;
-
- GType type_id = type_fun ();
- GType type_fundamental = g_type_fundamental (type_id);
- char *lower_case_prefix = str_replace (g_strndup (get_type_symbol, strlen (get_type_symbol) - strlen ("_get_type")), "_", "");
- if (type_fundamental == G_TYPE_OBJECT) {
- char *alt_lower_case_prefix;
- GIdlNodeInterface *ginode = (GIdlNodeInterface *) g_idl_node_new (G_IDL_NODE_OBJECT);
- ginode->node.name = g_strdup (g_type_name (type_id));
- igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
- g_hash_table_insert (igenerator->type_map, ginode->node.name, ginode);
- g_hash_table_insert (igenerator->type_by_lower_case_prefix, lower_case_prefix, ginode);
- alt_lower_case_prefix = g_ascii_strdown (ginode->node.name, -1);
- if (strcmp (alt_lower_case_prefix, lower_case_prefix) != 0) {
- /* alternative prefix sometimes necessary, for example for GdkWindow */
- g_hash_table_insert (igenerator->type_by_lower_case_prefix, alt_lower_case_prefix, ginode);
- } else {
- g_free (alt_lower_case_prefix);
- }
- ginode->gtype_name = ginode->node.name;
- ginode->gtype_init = get_type_symbol;
- ginode->parent = g_strdup (g_type_name (g_type_parent (type_id)));
-
- guint n_type_interfaces;
- GType *type_interfaces = g_type_interfaces (type_id, &n_type_interfaces);
- for (i = 0; i < n_type_interfaces; i++) {
- char *iface_name = g_strdup (g_type_name (type_interfaces[i]));
- /* workaround for AtkImplementorIface */
- if (g_str_has_suffix (iface_name, "Iface")) {
- iface_name[strlen (iface_name) - strlen ("Iface")] = '\0';
- }
- ginode->interfaces = g_list_append (ginode->interfaces, iface_name);
- }
-
- g_igenerator_process_properties (igenerator, ginode, type_id);
- g_igenerator_process_signals (igenerator, ginode, type_id);
- } else if (type_fundamental == G_TYPE_INTERFACE) {
- GIdlNodeInterface *ginode = (GIdlNodeInterface *) g_idl_node_new (G_IDL_NODE_INTERFACE);
- ginode->node.name = g_strdup (g_type_name (type_id));
- /* workaround for AtkImplementorIface */
- if (g_str_has_suffix (ginode->node.name, "Iface")) {
- ginode->node.name[strlen (ginode->node.name) - strlen ("Iface")] = '\0';
- }
- igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
- g_hash_table_insert (igenerator->type_map, ginode->node.name, ginode);
- g_hash_table_insert (igenerator->type_by_lower_case_prefix, lower_case_prefix, ginode);
- ginode->gtype_name = ginode->node.name;
- ginode->gtype_init = get_type_symbol;
-
- gboolean is_gobject = FALSE;
- guint n_iface_prereqs;
- GType *iface_prereqs = g_type_interface_prerequisites (type_id, &n_iface_prereqs);
- for (i = 0; i < n_iface_prereqs; i++) {
- if (g_type_fundamental (iface_prereqs[i]) == G_TYPE_OBJECT) {
- is_gobject = TRUE;
- }
- ginode->prerequisites = g_list_append (ginode->prerequisites, g_strdup (g_type_name (iface_prereqs[i])));
- }
-
- if (is_gobject) {
- g_igenerator_process_properties (igenerator, ginode, type_id);
- } else {
- g_type_default_interface_ref (type_id);
- }
- g_igenerator_process_signals (igenerator, ginode, type_id);
- } else if (type_fundamental == G_TYPE_BOXED) {
- GIdlNodeBoxed *ginode = (GIdlNodeBoxed *) g_idl_node_new (G_IDL_NODE_BOXED);
- ginode->node.name = g_strdup (g_type_name (type_id));
- igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
- g_hash_table_insert (igenerator->type_map, ginode->node.name, ginode);
- g_hash_table_insert (igenerator->type_by_lower_case_prefix, lower_case_prefix, ginode);
- ginode->gtype_name = ginode->node.name;
- ginode->gtype_init = get_type_symbol;
- } else if (type_fundamental == G_TYPE_ENUM) {
- GIdlNodeEnum *ginode = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_ENUM);
- ginode->node.name = g_strdup (g_type_name (type_id));
- igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
- g_hash_table_insert (igenerator->type_map, ginode->node.name, ginode);
- g_hash_table_insert (igenerator->type_by_lower_case_prefix, lower_case_prefix, ginode);
- ginode->gtype_name = ginode->node.name;
- ginode->gtype_init = get_type_symbol;
-
- GEnumClass *type_class = g_type_class_ref (type_id);
- for (i = 0; i < type_class->n_values; i++) {
- GIdlNodeValue *gival = (GIdlNodeValue *) g_idl_node_new (G_IDL_NODE_VALUE);
- ginode->values = g_list_append (ginode->values, gival);
- gival->node.name = g_strdup (type_class->values[i].value_name);
- gival->value = type_class->values[i].value;
- }
- } else if (type_fundamental == G_TYPE_FLAGS) {
- GIdlNodeEnum *ginode = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_FLAGS);
- ginode->node.name = g_strdup (g_type_name (type_id));
- igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
- g_hash_table_insert (igenerator->type_map, ginode->node.name, ginode);
- g_hash_table_insert (igenerator->type_by_lower_case_prefix, lower_case_prefix, ginode);
- ginode->gtype_name = ginode->node.name;
- ginode->gtype_init = get_type_symbol;
-
- GFlagsClass *type_class = g_type_class_ref (type_id);
- for (i = 0; i < type_class->n_values; i++) {
- GIdlNodeValue *gival = (GIdlNodeValue *) g_idl_node_new (G_IDL_NODE_VALUE);
- ginode->values = g_list_append (ginode->values, gival);
- gival->node.name = g_strdup (type_class->values[i].value_name);
- gival->value = type_class->values[i].value;
- }
- }
- }
- }
-}
-
-static GIdlNodeType *get_type_from_ctype (CType *ctype)
-{
- GIdlNodeType *gitype = (GIdlNodeType *) g_idl_node_new (G_IDL_NODE_TYPE);
- if (ctype->type == CTYPE_VOID) {
- gitype->unparsed = g_strdup ("void");
- } else if (ctype->type == CTYPE_BASIC_TYPE) {
- gitype->unparsed = g_strdup (ctype->name);
- } else if (ctype->type == CTYPE_TYPEDEF) {
- gitype->unparsed = g_strdup (ctype->name);
- } else if (ctype->type == CTYPE_STRUCT) {
- if (ctype->name == NULL) {
- /* anonymous struct */
- gitype->unparsed = g_strdup ("gpointer");
- } else {
- gitype->unparsed = g_strdup_printf ("struct %s", ctype->name);
- }
- } else if (ctype->type == CTYPE_UNION) {
- if (ctype->name == NULL) {
- /* anonymous union */
- gitype->unparsed = g_strdup ("gpointer");
- } else {
- gitype->unparsed = g_strdup_printf ("union %s", ctype->name);
- }
- } else if (ctype->type == CTYPE_ENUM) {
- if (ctype->name == NULL) {
- /* anonymous enum */
- gitype->unparsed = g_strdup ("gint");
- } else {
- gitype->unparsed = g_strdup_printf ("enum %s", ctype->name);
- }
- } else if (ctype->type == CTYPE_POINTER) {
- if (ctype->base_type->type == CTYPE_FUNCTION) {
- /* anonymous function pointer */
- gitype->unparsed = g_strdup ("GCallback");
- } else {
- GIdlNodeType *gibasetype = get_type_from_ctype (ctype->base_type);
- gitype->unparsed = g_strdup_printf ("%s*", gibasetype->unparsed);
- }
- } else if (ctype->type == CTYPE_ARRAY) {
- GIdlNodeType *gibasetype = get_type_from_ctype (ctype->base_type);
- gitype->unparsed = g_strdup_printf ("%s[]", gibasetype->unparsed);
- } else {
- gitype->unparsed = g_strdup ("unknown");
- }
- return gitype;
-}
-
-static void g_igenerator_process_function_symbol (GIGenerator *igenerator, CSymbol *sym)
-{
- GIdlNodeFunction *gifunc = (GIdlNodeFunction *) g_idl_node_new (G_IDL_NODE_FUNCTION);
- /* check whether this is a type method */
- char *last_underscore = strrchr (sym->ident, '_');
- while (last_underscore != NULL) {
- char *prefix = str_replace (g_strndup (sym->ident, last_underscore - sym->ident), "_", "");
- GIdlNode *ginode = g_hash_table_lookup (igenerator->type_by_lower_case_prefix, prefix);
- if (ginode != NULL) {
- gifunc->node.name = g_strdup (last_underscore + 1);
- if (strcmp (gifunc->node.name, "get_type") == 0) {
- /* ignore get_type functions in registered types */
- return;
- }
- if ((ginode->type == G_IDL_NODE_OBJECT || ginode->type == G_IDL_NODE_BOXED) && g_str_has_prefix (gifunc->node.name, "new")) {
- gifunc->is_constructor = TRUE;
- } else {
- gifunc->is_method = TRUE;
- }
- if (ginode->type == G_IDL_NODE_OBJECT || ginode->type == G_IDL_NODE_INTERFACE) {
- GIdlNodeInterface *giiface = (GIdlNodeInterface *) ginode;
- giiface->members = g_list_insert_sorted (giiface->members, gifunc, (GCompareFunc) g_idl_node_cmp);
- break;
- } else if (ginode->type == G_IDL_NODE_BOXED) {
- GIdlNodeBoxed *giboxed = (GIdlNodeBoxed *) ginode;
- giboxed->members = g_list_insert_sorted (giboxed->members, gifunc, (GCompareFunc) g_idl_node_cmp);
- break;
- } else if (ginode->type == G_IDL_NODE_STRUCT) {
- GIdlNodeStruct *gistruct = (GIdlNodeStruct *) ginode;
- gistruct->members = g_list_insert_sorted (gistruct->members, gifunc, (GCompareFunc) g_idl_node_cmp);
- break;
- } else if (ginode->type == G_IDL_NODE_UNION) {
- GIdlNodeUnion *giunion = (GIdlNodeUnion *) ginode;
- giunion->members = g_list_insert_sorted (giunion->members, gifunc, (GCompareFunc) g_idl_node_cmp);
- break;
- }
- } else if (strcmp (igenerator->lower_case_namespace, prefix) == 0) {
- gifunc->node.name = g_strdup (last_underscore + 1);
- gifunc->is_constructor = FALSE;
- gifunc->is_method = FALSE;
- igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, gifunc, (GCompareFunc) g_idl_node_cmp);
- break;
- }
- last_underscore = g_utf8_strrchr (sym->ident, last_underscore - sym->ident, '_');
- }
-
- /* create a namespace function if no prefix matches */
- if (gifunc->node.name == NULL) {
- gifunc->node.name = sym->ident;
- gifunc->is_constructor = FALSE;
- gifunc->is_method = FALSE;
- igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, gifunc, (GCompareFunc) g_idl_node_cmp);
- }
-
- gifunc->symbol = sym->ident;
- gifunc->result = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
- gifunc->result->type = get_type_from_ctype (sym->base_type->base_type);
- GList *param_l;
- int i;
- for (param_l = sym->base_type->child_list, i = 1; param_l != NULL; param_l = param_l->next, i++) {
- CSymbol *param_sym = param_l->data;
- GIdlNodeParam *param = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
- if (param_sym->ident == NULL) {
- param->node.name = g_strdup_printf ("p%d", i);
- } else {
- param->node.name = param_sym->ident;
- }
- param->type = get_type_from_ctype (param_sym->base_type);
- gifunc->parameters = g_list_append (gifunc->parameters, param);
- }
-}
-
-static void g_igenerator_process_unregistered_struct_typedef (GIGenerator *igenerator, CSymbol *sym, CType *struct_type)
-{
- GIdlNodeStruct *ginode = (GIdlNodeStruct *) g_idl_node_new (G_IDL_NODE_STRUCT);
- ginode->node.name = sym->ident;
- igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
- char *lower_case_prefix = g_ascii_strdown (sym->ident, -1);
- g_hash_table_insert (igenerator->type_map, sym->ident, ginode);
- g_hash_table_insert (igenerator->type_by_lower_case_prefix, lower_case_prefix, ginode);
-
- GList *member_l;
- for (member_l = struct_type->child_list; member_l != NULL; member_l = member_l->next) {
- CSymbol *member = member_l->data;
- GIdlNodeField *gifield = (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
- ginode->members = g_list_append (ginode->members, gifield);
- gifield->node.name = member->ident;
- gifield->type = get_type_from_ctype (member->base_type);
- }
-}
-
-static void g_igenerator_process_struct_typedef (GIGenerator *igenerator, CSymbol *sym)
-{
- CType *struct_type = sym->base_type;
- gboolean opaque_type = FALSE;
- if (struct_type->child_list == NULL) {
- g_assert (struct_type->name != NULL);
- CSymbol *struct_symbol = g_hash_table_lookup (igenerator->struct_or_union_or_enum_table, struct_type->name);
- if (struct_symbol != NULL) {
- struct_type = struct_symbol->base_type;
- }
- }
- if (struct_type->child_list == NULL) {
- opaque_type = TRUE;
- }
- GIdlNode *gitype = g_hash_table_lookup (igenerator->type_map, sym->ident);
- if (gitype != NULL) {
- /* struct of a GTypeInstance */
- if (!opaque_type && (gitype->type == G_IDL_NODE_OBJECT || gitype->type == G_IDL_NODE_INTERFACE)) {
- GIdlNodeInterface *ginode = (GIdlNodeInterface *) gitype;
- GList *member_l;
- /* ignore first field => parent */
- for (member_l = struct_type->child_list->next; member_l != NULL; member_l = member_l->next) {
- CSymbol *member = member_l->data;
- /* ignore private / reserved members */
- if (member->ident[0] == '_' || g_str_has_prefix (member->ident, "priv")) {
- continue;
- }
- GIdlNodeField *gifield = (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
- ginode->members = g_list_append (ginode->members, gifield);
- gifield->node.name = member->ident;
- gifield->type = get_type_from_ctype (member->base_type);
- }
- } else if (gitype->type == G_IDL_NODE_BOXED) {
- GIdlNodeBoxed *ginode = (GIdlNodeBoxed *) gitype;
- GList *member_l;
- for (member_l = struct_type->child_list; member_l != NULL; member_l = member_l->next) {
- CSymbol *member = member_l->data;
- GIdlNodeField *gifield = (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
- ginode->members = g_list_append (ginode->members, gifield);
- gifield->node.name = member->ident;
- gifield->type = get_type_from_ctype (member->base_type);
- }
- }
- } else if (!opaque_type && (g_str_has_suffix (sym->ident, "Class") || g_str_has_suffix (sym->ident, "Iface") || g_str_has_suffix (sym->ident, "Interface"))) {
- char *base_name;
- if (g_str_has_suffix (sym->ident, "Interface")) {
- base_name = g_strndup (sym->ident, strlen (sym->ident) - strlen ("Interface"));
- } else {
- base_name = g_strndup (sym->ident, strlen (sym->ident) - strlen ("Class"));
- }
- gitype = g_hash_table_lookup (igenerator->type_map, base_name);
- if (gitype == NULL || (gitype->type != G_IDL_NODE_OBJECT && gitype->type != G_IDL_NODE_INTERFACE)) {
- g_igenerator_process_unregistered_struct_typedef (igenerator, sym, struct_type);
- return;
- }
- GIdlNodeInterface *ginode = (GIdlNodeInterface *) gitype;
-
- /* ignore first field => parent */
- GList *member_l;
- for (member_l = struct_type->child_list->next; member_l != NULL; member_l = member_l->next) {
- CSymbol *member = member_l->data;
- /* ignore private / reserved members */
- if (member->ident[0] == '_') {
- continue;
- }
- if (member->base_type->type == CTYPE_POINTER && member->base_type->base_type->type == CTYPE_FUNCTION) {
- /* ignore default handlers of signals */
- gboolean found_signal = FALSE;
- GList *type_member_l;
- for (type_member_l = ginode->members; type_member_l != NULL; type_member_l = type_member_l->next) {
- GIdlNode *type_member = type_member_l->data;
- char *normalized_name = str_replace (type_member->name, "-", "_");
- if (type_member->type == G_IDL_NODE_SIGNAL && strcmp (normalized_name, member->ident) == 0) {
- GList *vfunc_param_l;
- GList *sig_param_l;
- GIdlNodeSignal *sig = (GIdlNodeSignal *) type_member;
- found_signal = TRUE;
- /* set signal parameter names */
- for (vfunc_param_l = member->base_type->base_type->child_list, sig_param_l = sig->parameters; vfunc_param_l != NULL && sig_param_l != NULL; vfunc_param_l = vfunc_param_l->next, sig_param_l = sig_param_l->next) {
- CSymbol *vfunc_param = vfunc_param_l->data;
- GIdlNodeParam *sig_param = sig_param_l->data;
- if (vfunc_param->ident != NULL) {
- g_free (sig_param->node.name);
- sig_param->node.name = g_strdup (vfunc_param->ident);
- }
- }
- break;
- }
- }
- if (found_signal) {
- continue;
- }
-
- GIdlNodeVFunc *givfunc = (GIdlNodeVFunc *) g_idl_node_new (G_IDL_NODE_VFUNC);
- givfunc->node.name = member->ident;
- ginode->members = g_list_insert_sorted (ginode->members, givfunc, (GCompareFunc) g_idl_node_cmp);
- givfunc->result = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
- givfunc->result->type = get_type_from_ctype (member->base_type->base_type->base_type);
- GList *param_l;
- int i;
- for (param_l = member->base_type->base_type->child_list, i = 1; param_l != NULL; param_l = param_l->next, i++) {
- CSymbol *param_sym = param_l->data;
- GIdlNodeParam *param = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
- if (param_sym->ident == NULL) {
- param->node.name = g_strdup_printf ("p%d", i);
- } else {
- param->node.name = param_sym->ident;
- }
- param->type = get_type_from_ctype (param_sym->base_type);
- givfunc->parameters = g_list_append (givfunc->parameters, param);
- }
- }
- }
- } else if (g_str_has_suffix (sym->ident, "Private")) {
- /* ignore private structs */
- } else {
- g_igenerator_process_unregistered_struct_typedef (igenerator, sym, struct_type);
- }
-}
-
-static void g_igenerator_process_union_typedef (GIGenerator *igenerator, CSymbol *sym)
-{
- CType *union_type = sym->base_type;
- gboolean opaque_type = FALSE;
- if (union_type->child_list == NULL) {
- g_assert (union_type->name != NULL);
- CSymbol *union_symbol = g_hash_table_lookup (igenerator->struct_or_union_or_enum_table, union_type->name);
- if (union_symbol != NULL) {
- union_type = union_symbol->base_type;
- }
- }
- if (union_type->child_list == NULL) {
- opaque_type = TRUE;
- }
- GIdlNode *gitype = g_hash_table_lookup (igenerator->type_map, sym->ident);
- if (gitype != NULL) {
- g_assert (gitype->type == G_IDL_NODE_BOXED);
- GIdlNodeBoxed *ginode = (GIdlNodeBoxed *) gitype;
- GList *member_l;
- for (member_l = union_type->child_list; member_l != NULL; member_l = member_l->next) {
- CSymbol *member = member_l->data;
- GIdlNodeField *gifield = (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
- ginode->members = g_list_append (ginode->members, gifield);
- gifield->node.name = member->ident;
- gifield->type = get_type_from_ctype (member->base_type);
- }
- } else {
- GIdlNodeUnion *ginode = (GIdlNodeUnion *) g_idl_node_new (G_IDL_NODE_UNION);
- ginode->node.name = sym->ident;
- igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
- char *lower_case_prefix = g_ascii_strdown (sym->ident, -1);
- g_hash_table_insert (igenerator->type_map, sym->ident, ginode);
- g_hash_table_insert (igenerator->type_by_lower_case_prefix, lower_case_prefix, ginode);
-
- ginode->node.name = sym->ident;
- GList *member_l;
- for (member_l = union_type->child_list; member_l != NULL; member_l = member_l->next) {
- CSymbol *member = member_l->data;
- GIdlNodeField *gifield = (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
- ginode->members = g_list_append (ginode->members, gifield);
- gifield->node.name = member->ident;
- gifield->type = get_type_from_ctype (member->base_type);
- }
- }
-}
-
-static void g_igenerator_process_enum_typedef (GIGenerator *igenerator, CSymbol *sym)
-{
- CType *enum_type = sym->base_type;
- if (enum_type->child_list == NULL) {
- g_assert (enum_type->name != NULL);
- CSymbol *enum_symbol = g_hash_table_lookup (igenerator->struct_or_union_or_enum_table, enum_type->name);
- if (enum_symbol != NULL) {
- enum_type = enum_symbol->base_type;
- }
- }
- if (enum_type->child_list == NULL) {
- /* opaque type */
- return;
- }
- GIdlNodeEnum *ginode = g_hash_table_lookup (igenerator->type_map, sym->ident);
- if (ginode != NULL) {
- return;
- }
-
- ginode = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_ENUM);
- ginode->node.name = sym->ident;
- igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
-
- GList *member_l;
- for (member_l = enum_type->child_list; member_l != NULL; member_l = member_l->next) {
- CSymbol *member = member_l->data;
- GIdlNodeValue *gival = (GIdlNodeValue *) g_idl_node_new (G_IDL_NODE_VALUE);
- ginode->values = g_list_append (ginode->values, gival);
- gival->node.name = member->ident;
- gival->value = member->const_int;
- }
-}
-
-static void g_igenerator_process_function_typedef (GIGenerator *igenerator, CSymbol *sym)
-{
- /* handle callback types */
- GIdlNodeFunction *gifunc = (GIdlNodeFunction *) g_idl_node_new (G_IDL_NODE_CALLBACK);
-
- gifunc->node.name = sym->ident;
- igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, gifunc, (GCompareFunc) g_idl_node_cmp);
-
- gifunc->symbol = sym->ident;
- gifunc->result = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
- gifunc->result->type = get_type_from_ctype (sym->base_type->base_type->base_type);
- GList *param_l;
- int i;
- for (param_l = sym->base_type->base_type->child_list, i = 1; param_l != NULL; param_l = param_l->next, i++) {
- CSymbol *param_sym = param_l->data;
- GIdlNodeParam *param = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
- if (param_sym->ident == NULL) {
- param->node.name = g_strdup_printf ("p%d", i);
- } else {
- param->node.name = param_sym->ident;
- }
- param->type = get_type_from_ctype (param_sym->base_type);
- gifunc->parameters = g_list_append (gifunc->parameters, param);
- }
-}
-
-static void g_igenerator_process_constant (GIGenerator *igenerator, CSymbol *sym)
-{
- GIdlNodeConstant *giconst = (GIdlNodeConstant *) g_idl_node_new (G_IDL_NODE_CONSTANT);
- giconst->node.name = sym->ident;
- igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, giconst, (GCompareFunc) g_idl_node_cmp);
-
- giconst->type = (GIdlNodeType *) g_idl_node_new (G_IDL_NODE_TYPE);
- if (sym->const_int_set) {
- giconst->type->unparsed = g_strdup ("int");
- giconst->value = g_strdup_printf ("%d", sym->const_int);
- } else if (sym->const_string != NULL) {
- giconst->type->unparsed = g_strdup ("char*");
- giconst->value = sym->const_string;
- }
-}
-
-static void g_igenerator_process_symbols (GIGenerator *igenerator)
-{
- GList *l;
- /* process type symbols first to ensure complete type hashtables */
- /* type symbols */
- for (l = igenerator->symbol_list; l != NULL; l = l->next) {
- CSymbol *sym = l->data;
- if (sym->ident[0] == '_') {
- /* ignore private / reserved symbols */
- continue;
- }
- if (sym->type == CSYMBOL_TYPE_TYPEDEF) {
- if (sym->base_type->type == CTYPE_STRUCT) {
- g_igenerator_process_struct_typedef (igenerator, sym);
- } else if (sym->base_type->type == CTYPE_UNION) {
- g_igenerator_process_union_typedef (igenerator, sym);
- } else if (sym->base_type->type == CTYPE_ENUM) {
- g_igenerator_process_enum_typedef (igenerator, sym);
- } else if (sym->base_type->type == CTYPE_POINTER && sym->base_type->base_type->type == CTYPE_FUNCTION) {
- g_igenerator_process_function_typedef (igenerator, sym);
- } else {
- GIdlNodeStruct *ginode = (GIdlNodeStruct *) g_idl_node_new (G_IDL_NODE_STRUCT);
- ginode->node.name = sym->ident;
- igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
- char *lower_case_prefix = g_ascii_strdown (sym->ident, -1);
- g_hash_table_insert (igenerator->type_map, sym->ident, ginode);
- g_hash_table_insert (igenerator->type_by_lower_case_prefix, lower_case_prefix, ginode);
- }
- }
- }
- /* other symbols */
- for (l = igenerator->symbol_list; l != NULL; l = l->next) {
- CSymbol *sym = l->data;
- if (sym->ident[0] == '_') {
- /* ignore private / reserved symbols */
- continue;
- }
- if (sym->type == CSYMBOL_TYPE_FUNCTION) {
- g_igenerator_process_function_symbol (igenerator, sym);
- } else if (sym->type == CSYMBOL_TYPE_CONST) {
- g_igenerator_process_constant (igenerator, sym);
- }
- }
-}
-
-void g_igenerator_add_symbol (GIGenerator *igenerator, CSymbol *symbol)
-{
- /* only add symbols of main file */
- gboolean found_filename = FALSE;
- GList *l;
- for (l = igenerator->filenames; l != NULL; l = l->next) {
- if (strcmp (l->data, igenerator->current_filename) == 0) {
- found_filename = TRUE;
- break;
- }
- }
- if (found_filename || igenerator->macro_scan) {
- igenerator->symbol_list = g_list_prepend (igenerator->symbol_list, symbol);
- }
-
- if (symbol->type == CSYMBOL_TYPE_TYPEDEF) {
- g_hash_table_insert (igenerator->typedef_table, symbol->ident, symbol);
- } else if (symbol->type == CSYMBOL_TYPE_STRUCT || symbol->type == CSYMBOL_TYPE_UNION || symbol->type == CSYMBOL_TYPE_ENUM) {
- g_hash_table_insert (igenerator->struct_or_union_or_enum_table, symbol->ident, symbol);
- }
-}
-
-gboolean g_igenerator_is_typedef (GIGenerator *igenerator, const char *name)
-{
- gboolean b = g_hash_table_lookup (igenerator->typedef_table, name) != NULL;
- return b;
-}
-
-void g_igenerator_generate (GIGenerator *igenerator)
-{
- GList *l;
- for (l = igenerator->symbol_list; l != NULL; l = l->next) {
- CSymbol *sym = l->data;
- if (sym->type == CSYMBOL_TYPE_FUNCTION && g_str_has_suffix (sym->ident, "_get_type")) {
- if (sym->base_type->child_list == NULL) {
- // ignore get_type functions with parameters
- igenerator->get_type_symbols = g_list_prepend (igenerator->get_type_symbols, sym->ident);
- }
- }
- }
- g_igenerator_process_types (igenerator);
- g_igenerator_process_symbols (igenerator);
-
- g_igenerator_write (igenerator, "<?xml version=\"1.0\"?>\n");
- g_igenerator_write_indent (igenerator, "<api version=\"1.0\">\n");
- module_generate (igenerator, igenerator->module);
- g_igenerator_write_unindent (igenerator, "</api>\n");
-}
-
-int main (int argc, char **argv)
-{
- g_type_init ();
-
- /* initialize threading as this may be required by libraries that we'll use */
- g_thread_init (NULL);
-
- GIGenerator *igenerator = g_igenerator_new ();
-
- int cpp_argc = 0;
- char **cpp_argv = g_new0 (char *, argc + 2);
- cpp_argv[cpp_argc++] = "cc";
- cpp_argv[cpp_argc++] = "-E";
-
- int i;
- for (i = 1; i < argc; i++) {
- if (argv[i][0] == '-') {
- switch (argv[i][1]) {
- case '-':
- if (g_str_has_prefix (argv[i], "--namespace=")) {
- igenerator->namespace = argv[i] + strlen ("--namespace=");
- g_free (igenerator->lower_case_namespace);
- igenerator->lower_case_namespace = g_ascii_strdown (igenerator->namespace, -1);
- }
- break;
- case 'I':
- case 'D':
- case 'U':
- cpp_argv[cpp_argc++] = argv[i];
- break;
- }
- } else if (g_str_has_suffix (argv[i], ".h")) {
- igenerator->filenames = g_list_append (igenerator->filenames, argv[i]);
- } else if (g_str_has_suffix (argv[i], ".la") ||
- g_str_has_suffix (argv[i], ".so") ||
- g_str_has_suffix (argv[i], ".dll")) {
- igenerator->libraries = g_list_append (igenerator->libraries, argv[i]);
- }
- }
-
-
- GError *error = NULL;
-
- char *tmp_name = NULL;
- FILE *f= fdopen (g_file_open_tmp ("gen-introspect-XXXXXX.h", &tmp_name, &error), "w");
-
-
- GList *l;
- for (l = igenerator->filenames; l != NULL; l = l->next) {
- fprintf (f, "#include <%s>\n", (char *) l->data);
- }
-
-
- fclose (f);
-
- cpp_argv[cpp_argc++] = tmp_name;
- cpp_argv[cpp_argc++] = NULL;
-
- int cpp_out = -1;
- g_spawn_async_with_pipes (NULL, cpp_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL, &cpp_out, NULL, &error);
- if (error != NULL) {
- g_error ("%s", error->message);
- }
-
- g_igenerator_parse (igenerator, fdopen (cpp_out, "r"));
-
- g_unlink (tmp_name);
-
- g_igenerator_parse_macros (igenerator);
-
- igenerator->module = g_idl_module_new (igenerator->namespace);
- g_igenerator_generate (igenerator);
-
- return 0;
-}
-
-CSymbol *csymbol_new (CSymbolType type) {
- CSymbol *s = g_new0 (CSymbol, 1);
- s->type = type;
- return s;
-}
-
-gboolean csymbol_get_const_boolean (CSymbol *symbol) {
- return (symbol->const_int_set && symbol->const_int) || symbol->const_string;
-}
-
-CType *ctype_new (CTypeType type) {
- CType *t = g_new0 (CType, 1);
- t->type = type;
- return t;
-}
-
-CType *ctype_copy (CType *type) {
- return g_memdup (type, sizeof (CType));
-}
-
-CType *cbasic_type_new (const char *name) {
- CType *basic_type = ctype_new (CTYPE_BASIC_TYPE);
- basic_type->name = g_strdup (name);
- return basic_type;
-}
-
-CType *ctypedef_new (const char *name) {
- CType *typedef_ = ctype_new (CTYPE_TYPEDEF);
- typedef_->name = g_strdup (name);
- return typedef_;
-}
-
-CType *cstruct_new (const char *name) {
- CType *struct_ = ctype_new (CTYPE_STRUCT);
- struct_->name = g_strdup (name);
- return struct_;
-}
-
-CType *cunion_new (const char *name) {
- CType *union_ = ctype_new (CTYPE_UNION);
- union_->name = g_strdup (name);
- return union_;
-}
-
-CType *cenum_new (const char *name) {
- CType *enum_ = ctype_new (CTYPE_ENUM);
- enum_->name = g_strdup (name);
- return enum_;
-}
-
-CType *cpointer_new (CType *base_type) {
- CType *pointer = ctype_new (CTYPE_POINTER);
- pointer->base_type = base_type;
- return pointer;
-}
-
-CType *carray_new (void) {
- CType *array = ctype_new (CTYPE_ARRAY);
- return array;
-}
-
-CType *cfunction_new (void) {
- CType *func = ctype_new (CTYPE_FUNCTION);
- return func;
-}
-
-static int eat_hspace (FILE *f) {
- int c;
- do {
- c = fgetc (f);
- } while (c == ' ' || c == '\t');
- return c;
-}
-
-static int eat_line (FILE *f, int c) {
- while (c != EOF && c != '\n') {
- c = fgetc (f);
- }
- if (c == '\n') {
- c = fgetc (f);
- if (c == ' ' || c == '\t') {
- c = eat_hspace (f);
- }
- }
- return c;
-}
-
-static int read_identifier (FILE *f, int c, char **identifier) {
- GString *id = g_string_new ("");
- while (isalnum (c) || c == '_') {
- g_string_append_c (id, c);
- c = fgetc (f);
- }
- *identifier = g_string_free (id, FALSE);
- return c;
-}
-
-static void g_igenerator_parse_macros (GIGenerator *igenerator) {
- GError *error = NULL;
- char *tmp_name = NULL;
- FILE *fmacros = fdopen (g_file_open_tmp ("gen-introspect-XXXXXX.h", &tmp_name, &error), "w+");
- g_unlink (tmp_name);
-
- GList *l;
- for (l = igenerator->filenames; l != NULL; l = l->next) {
- FILE *f = fopen (l->data, "r");
- int line = 1;
-
- GString *define_line;
- char *str;
- gboolean error_line = FALSE;
- int c = eat_hspace (f);
- while (c != EOF) {
- if (c != '#') {
- /* ignore line */
- c = eat_line (f, c);
- line++;
- continue;
- }
-
- /* print current location */
- str = g_strescape (l->data, "");
- fprintf (fmacros, "# %d \"%s\"\n", line, str);
- g_free (str);
-
- c = eat_hspace (f);
- c = read_identifier (f, c, &str);
- if (strcmp (str, "define") != 0 || (c != ' ' && c != '\t')) {
- g_free (str);
- /* ignore line */
- c = eat_line (f, c);
- line++;
- continue;
- }
- g_free (str);
- c = eat_hspace (f);
- c = read_identifier (f, c, &str);
- if (strlen (str) == 0 || (c != ' ' && c != '\t' && c != '(')) {
- g_free (str);
- /* ignore line */
- c = eat_line (f, c);
- line++;
- continue;
- }
- define_line = g_string_new ("#define ");
- g_string_append (define_line, str);
- g_free (str);
- if (c == '(') {
- while (c != ')') {
- g_string_append_c (define_line, c);
- c = fgetc (f);
- if (c == EOF || c == '\n') {
- error_line = TRUE;
- break;
- }
- }
- if (error_line) {
- g_string_free (define_line, TRUE);
- /* ignore line */
- c = eat_line (f, c);
- line++;
- continue;
- }
-
- g_assert (c == ')');
- g_string_append_c (define_line, c);
- c = fgetc (f);
-
- /* found function-like macro */
- fprintf (fmacros, "%s\n", define_line->str);
-
- g_string_free (define_line, TRUE);
- /* ignore rest of line */
- c = eat_line (f, c);
- line++;
- continue;
- }
- if (c != ' ' && c != '\t') {
- g_string_free (define_line, TRUE);
- /* ignore line */
- c = eat_line (f, c);
- line++;
- continue;
- }
- while (c != EOF && c != '\n') {
- g_string_append_c (define_line, c);
- c = fgetc (f);
- if (c == '\\') {
- c = fgetc (f);
- if (c == '\n') {
- /* fold lines when seeing backslash new-line sequence */
- c = fgetc (f);
- } else {
- g_string_append_c (define_line, '\\');
- }
- }
- }
-
- /* found object-like macro */
- fprintf (fmacros, "%s\n", define_line->str);
-
- c = eat_line (f, c);
- line++;
- }
-
- fclose (f);
- }
-
- igenerator->macro_scan = TRUE;
- rewind (fmacros);
- g_igenerator_parse (igenerator, fmacros);
- igenerator->macro_scan = FALSE;
-}
-
-
-
diff --git a/gobject-introspection/gen-introspect.h b/gobject-introspection/gen-introspect.h
deleted file mode 100644
index 91d4ab066..000000000
--- a/gobject-introspection/gen-introspect.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/* GObject introspection: gen-introspect
- *
- * Copyright (C) 2007 Jürg Billeter
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.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 <j@bitron.ch>
- */
-
-#ifndef __GEN_INTROSPECT_H__
-#define __GEN_INTROSPECT_H__
-
-#include <glib.h>
-#include "gidlmodule.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GIGenerator GIGenerator;
-typedef struct _CSymbol CSymbol;
-typedef struct _CType CType;
-
-struct _GIGenerator {
- const char *namespace;
- char *lower_case_namespace;
- /* specified files to be parsed */
- GList *filenames;
- GList *libraries;
- /* source reference of current lexer position */
- char *current_filename;
- GList *symbol_list;
- GHashTable *typedef_table;
- GHashTable *struct_or_union_or_enum_table;
-
- gboolean macro_scan;
-
- GIdlModule *module;
- GList *get_type_symbols;
- GHashTable *type_map;
- GHashTable *type_by_lower_case_prefix;
-
- int indent;
-};
-
-GIGenerator *g_igenerator_new (void);
-void g_igenerator_parse (GIGenerator *igenerator, FILE *f);
-void g_igenerator_add_symbol (GIGenerator *igenerator, CSymbol *symbol);
-gboolean g_igenerator_is_typedef (GIGenerator *igenerator, const char *name);
-void g_igenerator_generate (GIGenerator *igenerator);
-
-GIGenerator *the_igenerator;
-
-typedef enum {
- CSYMBOL_TYPE_INVALID,
- CSYMBOL_TYPE_CONST,
- CSYMBOL_TYPE_OBJECT,
- CSYMBOL_TYPE_FUNCTION,
- CSYMBOL_TYPE_STRUCT,
- CSYMBOL_TYPE_UNION,
- CSYMBOL_TYPE_ENUM,
- CSYMBOL_TYPE_TYPEDEF
-} CSymbolType;
-
-struct _CSymbol {
- CSymbolType type;
- int id;
- char *ident;
- CType *base_type;
- gboolean const_int_set;
- int const_int;
- char *const_string;
-};
-
-CSymbol *csymbol_new (CSymbolType type);
-gboolean csymbol_get_const_boolean (CSymbol *symbol);
-
-typedef enum {
- CTYPE_INVALID,
- CTYPE_VOID,
- CTYPE_BASIC_TYPE,
- CTYPE_TYPEDEF,
- CTYPE_STRUCT,
- CTYPE_UNION,
- CTYPE_ENUM,
- CTYPE_POINTER,
- CTYPE_ARRAY,
- CTYPE_FUNCTION
-} CTypeType;
-
-typedef enum {
- STORAGE_CLASS_NONE = 0,
- STORAGE_CLASS_TYPEDEF = 1 << 1,
- STORAGE_CLASS_EXTERN = 1 << 2,
- STORAGE_CLASS_STATIC = 1 << 3,
- STORAGE_CLASS_AUTO = 1 << 4,
- STORAGE_CLASS_REGISTER = 1 << 5
-} StorageClassSpecifier;
-
-typedef enum {
- TYPE_QUALIFIER_NONE = 0,
- TYPE_QUALIFIER_CONST = 1 << 1,
- TYPE_QUALIFIER_RESTRICT = 1 << 2,
- TYPE_QUALIFIER_VOLATILE = 1 << 3
-} TypeQualifier;
-
-typedef enum {
- FUNCTION_NONE = 0,
- FUNCTION_INLINE = 1 << 1
-} FunctionSpecifier;
-
-typedef enum {
- UNARY_ADDRESS_OF,
- UNARY_POINTER_INDIRECTION,
- UNARY_PLUS,
- UNARY_MINUS,
- UNARY_BITWISE_COMPLEMENT,
- UNARY_LOGICAL_NEGATION
-} UnaryOperator;
-
-struct _CType {
- CTypeType type;
- StorageClassSpecifier storage_class_specifier;
- TypeQualifier type_qualifier;
- FunctionSpecifier function_specifier;
- char *name;
- CType *base_type;
- GList *child_list;
-};
-
-CType *ctype_new (CTypeType type);
-CType *ctype_copy (CType *type);
-CType *cbasic_type_new (const char *name);
-CType *ctypedef_new (const char *name);
-CType *cstruct_new (const char *name);
-CType *cunion_new (const char *name);
-CType *cenum_new (const char *name);
-CType *cpointer_new (CType *base_type);
-CType *carray_new (void);
-CType *cfunction_new (void);
-
-G_END_DECLS
-
-#endif
-
diff --git a/gobject-introspection/gidlmodule.c b/gobject-introspection/gidlmodule.c
index 2d4929e0a..d17a249a0 100644
--- a/gobject-introspection/gidlmodule.c
+++ b/gobject-introspection/gidlmodule.c
@@ -23,20 +23,23 @@
#include "gidlmodule.h"
#include "gidlnode.h"
-#include "gmetadata.h"
#define ALIGN_VALUE(this, boundary) \
(( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
GIdlModule *
-g_idl_module_new (const gchar *name)
+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;
@@ -57,12 +60,12 @@ g_idl_module_free (GIdlModule *module)
g_free (module);
}
-void
+GMetadata *
g_idl_module_build_metadata (GIdlModule *module,
- GList *modules,
- guchar **metadata,
- gsize *length)
+ GList *modules)
{
+ guchar *metadata;
+ gsize length;
gint i;
GList *e;
Header *header;
@@ -116,6 +119,9 @@ g_idl_module_build_metadata (GIdlModule *module,
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;
@@ -202,7 +208,8 @@ g_idl_module_build_metadata (GIdlModule *module,
g_message ("reallocating to %d bytes", offset2);
- *metadata = g_realloc (data, offset2);
- *length = header->size = offset2;
+ metadata = g_realloc (data, offset2);
+ length = header->size = offset2;
+ return g_metadata_new_from_memory (metadata, length);
}
diff --git a/gobject-introspection/gidlmodule.h b/gobject-introspection/gidlmodule.h
index 17135764c..3564a75fc 100644
--- a/gobject-introspection/gidlmodule.h
+++ b/gobject-introspection/gidlmodule.h
@@ -22,6 +22,7 @@
#define __G_IDL_MODULE_H__
#include <glib.h>
+#include "gmetadata.h"
G_BEGIN_DECLS
@@ -31,16 +32,16 @@ typedef struct _GIdlModule GIdlModule;
struct _GIdlModule
{
gchar *name;
+ gchar *shared_library;
GList *entries;
};
-GIdlModule *g_idl_module_new (const gchar *name);
+GIdlModule *g_idl_module_new (const gchar *name,
+ const gchar *module_filename);
void g_idl_module_free (GIdlModule *module);
-void g_idl_module_build_metadata (GIdlModule *module,
- GList *modules,
- guchar **metadata,
- gsize *length);
+GMetadata * g_idl_module_build_metadata (GIdlModule *module,
+ GList *modules);
G_END_DECLS
diff --git a/gobject-introspection/gidlparser.c b/gobject-introspection/gidlparser.c
index 150861708..3d5292619 100644
--- a/gobject-introspection/gidlparser.c
+++ b/gobject-introspection/gidlparser.c
@@ -20,6 +20,7 @@
#include <stdlib.h>
#include <string.h>
+#include <stdlib.h>
#include <glib.h>
#include "gidlmodule.h"
@@ -92,6 +93,11 @@ parse_type_internal (gchar *str, gchar **rest)
{ "void", TYPE_TAG_VOID, 0 },
{ "gpointer", TYPE_TAG_VOID, 1 },
{ "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 },
@@ -1724,15 +1730,16 @@ start_element_handler (GMarkupParseContext *context,
case 'n':
if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_ROOT)
{
- const gchar *name;
+ 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);
+ ctx->current_module = g_idl_module_new (name, shared_library);
ctx->modules = g_list_append (ctx->modules, ctx->current_module);
ctx->state = STATE_NAMESPACE;
@@ -1863,7 +1870,7 @@ end_element_handler (GMarkupParseContext *context,
case STATE_NAMESPACE:
if (strcmp (element_name, "namespace") == 0)
- {
+ {
ctx->current_module = NULL;
ctx->state = STATE_ROOT;
}
diff --git a/gobject-introspection/gidlwriter.c b/gobject-introspection/gidlwriter.c
new file mode 100644
index 000000000..d46762bc0
--- /dev/null
+++ b/gobject-introspection/gidlwriter.c
@@ -0,0 +1,483 @@
+/* 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 <j@bitron.ch>
+ */
+
+#include <stdio.h>
+#include <glib.h>
+#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 ("<field name=\"%s\" type=\"%s\"/>\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 ("<member name=\"%s\" value=\"%d\"/>\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
+ ("<constant name=\"%s\" type=\"%s\" value=\"%s\"/>\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 ("<property name=\"%s\" "
+ "type=\"%s\" "
+ "readable=\"%s\" "
+ "writable=\"%s\" "
+ "construct=\"%s\" "
+ "construct-only=\"%s\"/>\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 =
+ g_markup_printf_escaped ("<return-type type=\"%s\"/>\n",
+ node->result->type->unparsed);
+ g_writer_write (writer, markup);
+ g_free (markup);
+
+ if (node->parameters != NULL)
+ {
+ GList *l;
+ g_writer_write_indent (writer, "<parameters>\n");
+ for (l = node->parameters; l != NULL; l = l->next)
+ {
+ GIdlNodeParam *param = l->data;
+ markup =
+ g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n",
+ param->node.name, param->type->unparsed);
+ g_writer_write (writer, markup);
+ g_free (markup);
+ }
+ g_writer_write_unindent (writer, "</parameters>\n");
+ }
+ markup = g_strdup_printf ("</%s>\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 ("<vfunc name=\"%s\">\n", node->node.name);
+ g_writer_write_indent (writer, markup);
+ g_free (markup);
+ markup =
+ g_markup_printf_escaped ("<return-type type=\"%s\"/>\n",
+ node->result->type->unparsed);
+ g_writer_write (writer, markup);
+ g_free (markup);
+ if (node->parameters != NULL)
+ {
+ GList *l;
+ g_writer_write_indent (writer, "<parameters>\n");
+ for (l = node->parameters; l != NULL; l = l->next)
+ {
+ GIdlNodeParam *param = l->data;
+ markup =
+ g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n",
+ param->node.name, param->type->unparsed);
+ g_writer_write (writer, markup);
+ g_free (markup);
+ }
+ g_writer_write_unindent (writer, "</parameters>\n");
+ }
+ g_writer_write_unindent (writer, "</vfunc>\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 ("<signal name=\"%s\" when=\"%s\">\n",
+ node->node.name, when);
+ g_writer_write_indent (writer, markup);
+ g_free (markup);
+ markup =
+ g_markup_printf_escaped ("<return-type type=\"%s\"/>\n",
+ node->result->type->unparsed);
+ g_writer_write (writer, markup);
+ g_free (markup);
+ if (node->parameters != NULL)
+ {
+ GList *l;
+ g_writer_write_indent (writer, "<parameters>\n");
+ for (l = node->parameters; l != NULL; l = l->next)
+ {
+ GIdlNodeParam *param = l->data;
+ markup =
+ g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n",
+ param->node.name, param->type->unparsed);
+ g_writer_write (writer, markup);
+ g_free (markup);
+ }
+ g_writer_write_unindent (writer, "</parameters>\n");
+ }
+ g_writer_write_unindent (writer, "</signal>\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 ("<object name=\"%s\" "
+ "parent=\"%s\" "
+ "type-name=\"%s\" "
+ "get-type=\"%s\">\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
+ ("<interface name=\"%s\" type-name=\"%s\" get-type=\"%s\">\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, "<implements>\n");
+ for (l = node->interfaces; l != NULL; l = l->next)
+ {
+ markup =
+ g_markup_printf_escaped ("<interface name=\"%s\"/>\n",
+ (char *) l->data);
+ g_writer_write (writer, markup);
+ g_free (markup);
+ }
+ g_writer_write_unindent (writer, "</implements>\n");
+ }
+ else if (node->node.type == G_IDL_NODE_INTERFACE
+ && node->prerequisites != NULL)
+ {
+ GList *l;
+ g_writer_write_indent (writer, "<requires>\n");
+ for (l = node->prerequisites; l != NULL; l = l->next)
+ {
+ markup =
+ g_markup_printf_escaped ("<interface name=\"%s\"/>\n",
+ (char *) l->data);
+ g_writer_write (writer, markup);
+ g_free (markup);
+ }
+ g_writer_write_unindent (writer, "</requires>\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, "</object>\n");
+ }
+ else if (node->node.type == G_IDL_NODE_INTERFACE)
+ {
+ g_writer_write_unindent (writer, "</interface>\n");
+ }
+}
+
+static void
+struct_generate (GIdlWriter * writer, GIdlNodeStruct * node)
+{
+ GList *l;
+ char *markup =
+ g_markup_printf_escaped ("<struct name=\"%s\">\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, "</struct>\n");
+}
+
+static void
+union_generate (GIdlWriter * writer, GIdlNodeUnion * node)
+{
+ GList *l;
+ char *markup =
+ g_markup_printf_escaped ("<union name=\"%s\">\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, "</union>\n");
+}
+
+static void
+boxed_generate (GIdlWriter * writer, GIdlNodeBoxed * node)
+{
+ GList *l;
+ char *markup =
+ g_markup_printf_escaped
+ ("<boxed name=\"%s\" type-name=\"%s\" get-type=\"%s\">\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, "</boxed>\n");
+}
+
+static void
+enum_generate (GIdlWriter * writer, GIdlNodeEnum * node)
+{
+ GList *l;
+ 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 =
+ g_markup_printf_escaped ("<%s name=\"%s\">\n", tag_name, node->node.name);
+ g_writer_write_indent (writer, markup);
+ g_free (markup);
+
+ for (l = node->values; l != NULL; l = l->next)
+ {
+ node_generate (writer, l->data);
+ }
+
+ markup = g_strdup_printf ("</%s>\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 ("<namespace name=\"%s\">\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, "</namespace>\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, "<?xml version=\"1.0\"?>\n");
+ g_writer_write_indent (writer, "<api version=\"1.0\">\n");
+ g_writer_write_module (writer, module);
+ g_writer_write_unindent (writer, "</api>\n");
+
+ if (filename)
+ fclose (writer->output);
+}
diff --git a/gobject-introspection/gidlwriter.h b/gobject-introspection/gidlwriter.h
new file mode 100644
index 000000000..5d41a0c6a
--- /dev/null
+++ b/gobject-introspection/gidlwriter.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__ */
diff --git a/gobject-introspection/girepository.h b/gobject-introspection/girepository.h
new file mode 100644
index 000000000..7ad1067a1
--- /dev/null
+++ b/gobject-introspection/girepository.h
@@ -0,0 +1,452 @@
+/* GObject introspection: Repository
+ *
+ * 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_IREPOSITORY_H__
+#define __G_IREPOSITORY_H__
+
+#include <glib-object.h>
+#include <gmodule.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_IREPOSITORY (g_irepository_get_type ())
+#define G_IREPOSITORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_IREPOSITORY, GIRepository))
+
+typedef struct _GIRepository GIRepository;
+typedef struct _GIRepositoryClass GIRepositoryClass;
+typedef struct _GIRepositoryPrivate GIRepositoryPrivate;
+typedef struct _GIBaseInfo GIBaseInfo;
+typedef struct _GICallableInfo GICallableInfo;
+typedef struct _GIFunctionInfo GIFunctionInfo;
+typedef struct _GICallbackInfo GICallbackInfo;
+typedef struct _GIRegisteredTypeInfo GIRegisteredTypeInfo;
+typedef struct _GIStructInfo GIStructInfo;
+typedef struct _GIUnionInfo GIUnionInfo;
+typedef struct _GIEnumInfo GIEnumInfo;
+typedef struct _GIObjectInfo GIObjectInfo;
+typedef struct _GIInterfaceInfo GIInterfaceInfo;
+typedef struct _GIConstantInfo GIConstantInfo;
+typedef struct _GIValueInfo GIValueInfo;
+typedef struct _GISignalInfo GISignalInfo;
+typedef struct _GIVFuncInfo GIVFuncInfo;
+typedef struct _GIPropertyInfo GIPropertyInfo;
+typedef struct _GIFieldInfo GIFieldInfo;
+typedef struct _GIArgInfo GIArgInfo;
+typedef struct _GITypeInfo GITypeInfo;
+typedef struct _GIErrorDomainInfo GIErrorDomainInfo;
+typedef struct _GIUnresolvedInfo GIUnresolvedInfo;
+typedef struct _GMetadata GMetadata;
+
+struct _GIRepository
+{
+ GObject parent;
+
+ /*< private >*/
+ GIRepositoryPrivate *priv;
+};
+
+struct _GIRepositoryClass
+{
+ GObjectClass parent;
+};
+
+
+/* Repository */
+
+GType g_irepository_get_type (void) G_GNUC_CONST;
+GIRepository *g_irepository_get_default (void);
+const gchar * g_irepository_register (GIRepository *repository,
+ GMetadata *metadata);
+void g_irepository_unregister (GIRepository *repository,
+ const gchar *namespace);
+const gchar * g_irepository_register_file (GIRepository *repository,
+ const gchar *filename,
+ GError **error);
+gboolean g_irepository_is_registered (GIRepository *repository,
+ const gchar *namespace);
+GIBaseInfo * g_irepository_find_by_name (GIRepository *repository,
+ const gchar *namespace,
+ const gchar *name);
+gchar ** g_irepository_get_namespaces (GIRepository *repository);
+GIBaseInfo * g_irepository_find_by_gtype (GIRepository *repository,
+ GType gtype);
+gint g_irepository_get_n_infos (GIRepository *repository,
+ const gchar *namespace);
+GIBaseInfo * g_irepository_get_info (GIRepository *repository,
+ const gchar *namespace,
+ gint index);
+const gchar * g_irepository_get_shared_library (GIRepository *repository,
+ const gchar *namespace);
+/* Metadata */
+
+GMetadata * g_metadata_new_from_memory (guchar *memory,
+ gsize len);
+GMetadata * g_metadata_new_from_const_memory (const guchar *memory,
+ gsize len);
+GMetadata * g_metadata_new_from_mapped_file (GMappedFile *mfile);
+void g_metadata_free (GMetadata *metadata);
+void g_metadata_set_module (GMetadata *metadata,
+ GModule *module);
+const gchar * g_metadata_get_namespace (GMetadata *metadata);
+
+typedef enum
+{
+ G_IREPOSITORY_ERROR_METADATA_NOT_FOUND,
+ G_IREPOSITORY_ERROR_NAMESPACE_MISMATCH,
+ G_IREPOSITORY_ERROR_LIBRARY_NOT_FOUND
+} GIRepositoryError;
+
+#define G_IREPOSITORY_ERROR (g_irepository_error_quark ())
+
+GQuark g_irepository_error_quark (void);
+
+
+/* Types of objects registered in the repository */
+
+typedef enum
+{
+ GI_INFO_TYPE_INVALID,
+ GI_INFO_TYPE_FUNCTION,
+ GI_INFO_TYPE_CALLBACK,
+ GI_INFO_TYPE_STRUCT,
+ GI_INFO_TYPE_BOXED,
+ GI_INFO_TYPE_ENUM,
+ GI_INFO_TYPE_FLAGS,
+ GI_INFO_TYPE_OBJECT,
+ GI_INFO_TYPE_INTERFACE,
+ GI_INFO_TYPE_CONSTANT,
+ GI_INFO_TYPE_ERROR_DOMAIN,
+ GI_INFO_TYPE_UNION,
+ GI_INFO_TYPE_VALUE,
+ GI_INFO_TYPE_SIGNAL,
+ GI_INFO_TYPE_VFUNC,
+ GI_INFO_TYPE_PROPERTY,
+ GI_INFO_TYPE_FIELD,
+ GI_INFO_TYPE_ARG,
+ GI_INFO_TYPE_TYPE,
+ GI_INFO_TYPE_UNRESOLVED
+} GIInfoType;
+
+
+/* GIBaseInfo */
+
+GIBaseInfo * g_base_info_ref (GIBaseInfo *info);
+void g_base_info_unref (GIBaseInfo *info);
+GIInfoType g_base_info_get_type (GIBaseInfo *info);
+const gchar * g_base_info_get_name (GIBaseInfo *info);
+const gchar * g_base_info_get_namespace (GIBaseInfo *info);
+gboolean g_base_info_is_deprecated (GIBaseInfo *info);
+const gchar * g_base_info_get_annotation (GIBaseInfo *info,
+ const gchar *name);
+GIBaseInfo * g_base_info_get_container (GIBaseInfo *info);
+GMetadata * g_base_info_get_metadata (GIBaseInfo *info);
+
+GIBaseInfo * g_info_new (GIInfoType type,
+ GIBaseInfo *container,
+ GMetadata *metadata,
+ guint32 offset);
+
+
+/* GIFunctionInfo */
+
+typedef enum
+{
+ GI_FUNCTION_IS_METHOD = 1 << 0,
+ GI_FUNCTION_IS_CONSTRUCTOR = 1 << 1,
+ GI_FUNCTION_IS_GETTER = 1 << 2,
+ GI_FUNCTION_IS_SETTER = 1 << 3,
+ GI_FUNCTION_WRAPS_VFUNC = 1 << 4
+} GIFunctionInfoFlags;
+
+const gchar * g_function_info_get_symbol (GIFunctionInfo *info);
+GIFunctionInfoFlags g_function_info_get_flags (GIFunctionInfo *info);
+GIPropertyInfo * g_function_info_get_property (GIFunctionInfo *info);
+GIVFuncInfo * g_function_info_get_vfunc (GIFunctionInfo *info);
+
+typedef union
+{
+ gboolean v_boolean;
+ gint8 v_int8;
+ guint8 v_uint8;
+ gint16 v_int16;
+ guint16 v_uint16;
+ gint32 v_int32;
+ guint32 v_uint32;
+ gint64 v_int64;
+ guint64 v_uint64;
+ gfloat v_float;
+ gdouble v_double;
+ gint v_int;
+ guint v_uint;
+ glong v_long;
+ gulong v_ulong;
+ gssize v_ssize;
+ gsize v_size;
+ gchar * v_string;
+ gpointer v_pointer;
+} GArgument;
+
+#define G_INVOKE_ERROR (g_invoke_error_quark ())
+GQuark g_invoke_error_quark (void);
+
+typedef enum
+{
+ G_INVOKE_ERROR_FAILED,
+ G_INVOKE_ERROR_SYMBOL_NOT_FOUND,
+ G_INVOKE_ERROR_ARGUMENT_MISMATCH
+} GInvokeError;
+
+gboolean g_function_info_invoke (GIFunctionInfo *info,
+ const GArgument *in_args,
+ int n_in_args,
+ const GArgument *out_args,
+ int n_out_args,
+ GArgument *return_value,
+ GError **error);
+
+
+/* GICallableInfo */
+
+typedef enum {
+ GI_TRANSFER_NOTHING,
+ GI_TRANSFER_CONTAINER,
+ GI_TRANSFER_EVERYTHING
+} GITransfer;
+
+GITypeInfo * g_callable_info_get_return_type (GICallableInfo *info);
+GITransfer g_callable_info_get_caller_owns (GICallableInfo *info);
+gboolean g_callable_info_may_return_null (GICallableInfo *info);
+gint g_callable_info_get_n_args (GICallableInfo *info);
+GIArgInfo * g_callable_info_get_arg (GICallableInfo *info,
+ gint n);
+
+/* GIArgInfo */
+
+typedef enum {
+ GI_DIRECTION_IN,
+ GI_DIRECTION_OUT,
+ GI_DIRECTION_INOUT
+} GIDirection;
+
+GIDirection g_arg_info_get_direction (GIArgInfo *info);
+gboolean g_arg_info_is_dipper (GIArgInfo *info);
+gboolean g_arg_info_is_return_value (GIArgInfo *info);
+gboolean g_arg_info_is_optional (GIArgInfo *info);
+gboolean g_arg_info_may_be_null (GIArgInfo *info);
+GITransfer g_arg_info_get_ownership_transfer (GIArgInfo *info);
+GITypeInfo * g_arg_info_get_type (GIArgInfo *info);
+
+
+/* GITypeInfo */
+
+typedef enum {
+ GI_TYPE_TAG_VOID = 0,
+ GI_TYPE_TAG_BOOLEAN = 1,
+ GI_TYPE_TAG_INT8 = 2,
+ GI_TYPE_TAG_UINT8 = 3,
+ GI_TYPE_TAG_INT16 = 4,
+ GI_TYPE_TAG_UINT16 = 5,
+ GI_TYPE_TAG_INT32 = 6,
+ GI_TYPE_TAG_UINT32 = 7,
+ GI_TYPE_TAG_INT64 = 8,
+ GI_TYPE_TAG_UINT64 = 9,
+ GI_TYPE_TAG_INT = 10,
+ GI_TYPE_TAG_UINT = 11,
+ GI_TYPE_TAG_LONG = 12,
+ GI_TYPE_TAG_ULONG = 13,
+ GI_TYPE_TAG_SSIZE = 14,
+ GI_TYPE_TAG_SIZE = 15,
+ GI_TYPE_TAG_FLOAT = 16,
+ GI_TYPE_TAG_DOUBLE = 17,
+ GI_TYPE_TAG_UTF8 = 18,
+ GI_TYPE_TAG_FILENAME = 19,
+ GI_TYPE_TAG_ARRAY = 20,
+ GI_TYPE_TAG_INTERFACE = 21,
+ GI_TYPE_TAG_GLIST = 22,
+ GI_TYPE_TAG_GSLIST = 23,
+ GI_TYPE_TAG_GHASH = 24,
+ GI_TYPE_TAG_ERROR = 25
+} GITypeTag;
+
+gboolean g_type_info_is_pointer (GITypeInfo *info);
+GITypeTag g_type_info_get_tag (GITypeInfo *info);
+GITypeInfo * g_type_info_get_param_type (GITypeInfo *info,
+ gint n);
+GIBaseInfo * g_type_info_get_interface (GITypeInfo *info);
+gint g_type_info_get_array_length (GITypeInfo *info);
+gboolean g_type_info_is_zero_terminated (GITypeInfo *info);
+
+gint g_type_info_get_n_error_domains (GITypeInfo *info);
+GIErrorDomainInfo *g_type_info_get_error_domain (GITypeInfo *info,
+ gint n);
+
+/* GIErrorDomainInfo */
+
+const gchar * g_error_domain_info_get_quark (GIErrorDomainInfo *info);
+GIInterfaceInfo * g_error_domain_info_get_codes (GIErrorDomainInfo *info);
+
+
+/* GIValueInfo */
+
+glong g_value_info_get_value (GIValueInfo *info);
+
+
+/* GIFieldInfo */
+
+typedef enum
+{
+ GI_FIELD_IS_READABLE = 1 << 0,
+ GI_FIELD_IS_WRITABLE = 1 << 1
+} GIFieldInfoFlags;
+
+GIFieldInfoFlags g_field_info_get_flags (GIFieldInfo *info);
+gint g_field_info_get_size (GIFieldInfo *info);
+gint g_field_info_get_offset (GIFieldInfo *info);
+GITypeInfo * g_field_info_get_type (GIFieldInfo *info);
+
+
+/* GIUnionInfo */
+gint g_union_info_get_n_fields (GIUnionInfo *info);
+GIFieldInfo * g_union_info_get_field (GIUnionInfo *info,
+ gint n);
+gint g_union_info_get_n_methods (GIUnionInfo *info);
+GIFunctionInfo * g_union_info_get_method (GIUnionInfo *info,
+ gint n);
+gboolean g_union_info_is_discriminated (GIUnionInfo *info);
+gint g_union_info_get_discriminator_offset (GIUnionInfo *info);
+GITypeInfo * g_union_info_get_discriminator_type (GIUnionInfo *info);
+GIConstantInfo * g_union_info_get_discriminator (GIUnionInfo *info,
+ gint n);
+
+
+/* GIStructInfo */
+gint g_struct_info_get_n_fields (GIStructInfo *info);
+GIFieldInfo * g_struct_info_get_field (GIStructInfo *info,
+ gint n);
+gint g_struct_info_get_n_methods (GIStructInfo *info);
+GIFunctionInfo * g_struct_info_get_method (GIStructInfo *info,
+ gint n);
+GIFunctionInfo * g_struct_info_find_method (GIStructInfo *info,
+ const gchar *name);
+
+/* GIRegisteredTypeInfo */
+
+const gchar * g_registered_type_info_get_type_name (GIRegisteredTypeInfo *info);
+const gchar * g_registered_type_info_get_type_init (GIRegisteredTypeInfo *info);
+
+
+/* GIEnumInfo */
+
+gint g_enum_info_get_n_values (GIEnumInfo *info);
+GIValueInfo * g_enum_info_get_value (GIEnumInfo *info,
+ gint n);
+
+/* GIObjectInfo */
+
+const gchar * g_object_info_get_type_name (GIObjectInfo *info);
+const gchar * g_object_info_get_type_init (GIObjectInfo *info);
+GIObjectInfo * g_object_info_get_parent (GIObjectInfo *info);
+gint g_object_info_get_n_interfaces (GIObjectInfo *info);
+GIInterfaceInfo * g_object_info_get_interface (GIObjectInfo *info,
+ gint n);
+gint g_object_info_get_n_fields (GIObjectInfo *info);
+GIFieldInfo * g_object_info_get_field (GIObjectInfo *info,
+ gint n);
+gint g_object_info_get_n_properties (GIObjectInfo *info);
+GIPropertyInfo * g_object_info_get_property (GIObjectInfo *info,
+ gint n);
+gint g_object_info_get_n_methods (GIObjectInfo *info);
+GIFunctionInfo * g_object_info_get_method (GIObjectInfo *info,
+ gint n);
+GIFunctionInfo * g_object_info_find_method (GIObjectInfo *info,
+ const gchar *name);
+gint g_object_info_get_n_signals (GIObjectInfo *info);
+GISignalInfo * g_object_info_get_signal (GIObjectInfo *info,
+ gint n);
+gint g_object_info_get_n_vfuncs (GIObjectInfo *info);
+GIVFuncInfo * g_object_info_get_vfunc (GIObjectInfo *info,
+ gint n);
+gint g_object_info_get_n_constants (GIObjectInfo *info);
+GIConstantInfo * g_object_info_get_constant (GIObjectInfo *info,
+ gint n);
+
+
+/* GIInterfaceInfo */
+
+gint g_interface_info_get_n_prerequisites (GIInterfaceInfo *info);
+GIBaseInfo * g_interface_info_get_prerequisite (GIInterfaceInfo *info,
+ gint n);
+gint g_interface_info_get_n_properties (GIInterfaceInfo *info);
+GIPropertyInfo * g_interface_info_get_property (GIInterfaceInfo *info,
+ gint n);
+gint g_interface_info_get_n_methods (GIInterfaceInfo *info);
+GIFunctionInfo * g_interface_info_get_method (GIInterfaceInfo *info,
+ gint n);
+GIFunctionInfo * g_interface_info_find_method (GIInterfaceInfo *info,
+ const gchar *name);
+gint g_interface_info_get_n_signals (GIInterfaceInfo *info);
+GISignalInfo * g_interface_info_get_signal (GIInterfaceInfo *info,
+ gint n);
+gint g_interface_info_get_n_vfuncs (GIInterfaceInfo *info);
+GIVFuncInfo * g_interface_info_get_vfunc (GIInterfaceInfo *info,
+ gint n);
+gint g_interface_info_get_n_constants (GIInterfaceInfo *info);
+GIConstantInfo * g_interface_info_get_constant (GIInterfaceInfo *info,
+ gint n);
+
+
+/* GIPropertyInfo */
+
+GParamFlags g_property_info_get_flags (GIPropertyInfo *info);
+GITypeInfo * g_property_info_get_type (GIPropertyInfo *info);
+
+
+/* GISignalInfo */
+
+GSignalFlags g_signal_info_get_flags (GISignalInfo *info);
+GIVFuncInfo * g_signal_info_get_class_closure (GISignalInfo *info);
+gboolean g_signal_info_true_stops_emit (GISignalInfo *info);
+
+
+/* GIVFuncInfo */
+
+typedef enum
+{
+ GI_VFUNC_MUST_CHAIN_UP = 1 << 0,
+ GI_VFUNC_MUST_OVERRIDE = 1 << 1,
+ GI_VFUNC_MUST_NOT_OVERRIDE = 1 << 2
+} GIVFuncInfoFlags;
+
+GIVFuncInfoFlags g_vfunc_info_get_flags (GIVFuncInfo *info);
+gint g_vfunc_info_get_offset (GIVFuncInfo *info);
+GISignalInfo * g_vfunc_info_get_signal (GIVFuncInfo *info);
+
+
+/* GIConstantInfo */
+
+GITypeInfo * g_constant_info_get_type (GIConstantInfo *info);
+gint g_constant_info_get_value (GIConstantInfo *info,
+ GArgument *value);
+
+
+G_END_DECLS
+
+#endif /* __G_IREPOSITORY_H__ */
+
diff --git a/gobject-introspection/gmetadata.c b/gobject-introspection/gmetadata.c
new file mode 100644
index 000000000..b68039043
--- /dev/null
+++ b/gobject-introspection/gmetadata.c
@@ -0,0 +1,1876 @@
+/* GObject introspection: metadata validation, auxiliary functions
+ * related to the binary metadata 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 <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include "gmetadata.h"
+
+
+#define ALIGN_VALUE(this, boundary) \
+ (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
+
+
+DirEntry *
+g_metadata_get_dir_entry (GMetadata *metadata,
+ guint16 index)
+{
+ Header *header = (Header *)metadata->data;
+
+ return (DirEntry *)&metadata->data[header->directory + (index - 1) * header->entry_blob_size];
+}
+
+void
+g_metadata_check_sanity (void)
+{
+ /* Check that struct layout is as we expect */
+ g_assert (sizeof (Header) == 100);
+ g_assert (sizeof (DirEntry) == 12);
+ g_assert (sizeof (SimpleTypeBlob) == 4);
+ g_assert (sizeof (ArgBlob) == 12);
+ g_assert (sizeof (SignatureBlob) == 8);
+ g_assert (sizeof (CommonBlob) == 8);
+ g_assert (sizeof (FunctionBlob) == 16);
+ g_assert (sizeof (InterfaceTypeBlob) == 4);
+ g_assert (sizeof (ArrayTypeBlob) == 8);
+ g_assert (sizeof (ParamTypeBlob) == 4);
+ g_assert (sizeof (ErrorTypeBlob) == 4);
+ g_assert (sizeof (ErrorDomainBlob) == 16);
+ g_assert (sizeof (ValueBlob) == 12);
+ g_assert (sizeof (FieldBlob) == 12);
+ g_assert (sizeof (RegisteredTypeBlob) == 16);
+ g_assert (sizeof (StructBlob) == 20);
+ g_assert (sizeof (EnumBlob) == 20);
+ g_assert (sizeof (PropertyBlob) == 12);
+ g_assert (sizeof (SignalBlob) == 12);
+ g_assert (sizeof (VFuncBlob) == 16);
+ g_assert (sizeof (ObjectBlob) == 32);
+ g_assert (sizeof (InterfaceBlob) == 28);
+ g_assert (sizeof (ConstantBlob) == 20);
+ g_assert (sizeof (AnnotationBlob) == 12);
+ g_assert (sizeof (UnionBlob) == 28);
+}
+
+
+static gboolean
+is_aligned (guint32 offset)
+{
+ return offset == ALIGN_VALUE (offset, 4);
+}
+
+#define MAX_NAME_LEN 200
+
+static gboolean
+is_name (const guchar *data, guint32 offset)
+{
+ gchar *name;
+
+ name = (gchar*)&data[offset];
+
+ if (!memchr (name, '\0', MAX_NAME_LEN))
+ return FALSE;
+
+ if (strspn (name, G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "-_") < strlen (name))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_header (GMetadata *metadata,
+ GError **error)
+{
+ Header *header;
+
+ if (metadata->len < sizeof (Header))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ header = (Header *)metadata->data;
+
+ if (strncmp (header->magic, G_IDL_MAGIC, 16) != 0)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_HEADER,
+ "Magic string not found");
+ return FALSE;
+
+ }
+
+ if (header->major_version != 1 || header->minor_version != 0)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_HEADER,
+ "Version mismatch");
+ return FALSE;
+
+ }
+
+ if (header->n_entries < header->n_local_entries)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_HEADER,
+ "Inconsistent entry counts");
+ return FALSE;
+ }
+
+ if (header->size != metadata->len)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_HEADER,
+ "Metadata size mismatch");
+ return FALSE;
+ }
+
+ if (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)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_HEADER,
+ "Blob size mismatch");
+ return FALSE;
+ }
+
+ if (!is_aligned (header->directory))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_HEADER,
+ "Misaligned directory");
+ return FALSE;
+ }
+
+ if (!is_aligned (header->annotations))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_HEADER,
+ "Misaligned annotations");
+ return FALSE;
+ }
+
+ if (header->annotations == 0 && header->n_annotations > 0)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_HEADER,
+ "Wrong number of annotations");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, header->namespace))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_HEADER,
+ "Invalid namespace name");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean validate_type_blob (GMetadata *metadata,
+ guint32 offset,
+ guint32 signature_offset,
+ gboolean return_type,
+ GError **error);
+
+static gboolean
+validate_array_type_blob (GMetadata *metadata,
+ guint32 offset,
+ guint32 signature_offset,
+ gboolean return_type,
+ GError **error)
+{
+ ArrayTypeBlob *blob;
+
+ blob = (ArrayTypeBlob*)&metadata->data[offset];
+
+ if (!blob->pointer)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Pointer type exected for tag %d", blob->tag);
+ return FALSE;
+ }
+
+ /* FIXME validate length */
+
+ if (!validate_type_blob (metadata,
+ offset + G_STRUCT_OFFSET (ArrayTypeBlob, type),
+ 0, FALSE, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_iface_type_blob (GMetadata *metadata,
+ guint32 offset,
+ guint32 signature_offset,
+ gboolean return_type,
+ GError **error)
+{
+ InterfaceTypeBlob *blob;
+ Header *header;
+
+ header = (Header *)metadata->data;
+
+ blob = (InterfaceTypeBlob*)&metadata->data[offset];
+
+ if (blob->interface == 0 || blob->interface > header->n_entries)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid directory index %d", blob->interface);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_param_type_blob (GMetadata *metadata,
+ guint32 offset,
+ guint32 signature_offset,
+ gboolean return_type,
+ gint n_params,
+ GError **error)
+{
+ ParamTypeBlob *blob;
+ gint i;
+
+ blob = (ParamTypeBlob*)&metadata->data[offset];
+
+ if (!blob->pointer)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Pointer type exected for tag %d", blob->tag);
+ return FALSE;
+ }
+
+ if (blob->n_types != n_params)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Parameter type number mismatch");
+ return FALSE;
+ }
+
+ for (i = 0; i < n_params; i++)
+ {
+ if (!validate_type_blob (metadata,
+ offset + sizeof (ParamTypeBlob) +
+ i * sizeof (SimpleTypeBlob),
+ 0, FALSE, error))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_error_type_blob (GMetadata *metadata,
+ guint32 offset,
+ guint32 signature_offset,
+ gboolean return_type,
+ GError **error)
+{
+ ErrorTypeBlob *blob;
+ Header *header;
+ gint i;
+ DirEntry *entry;
+
+ blob = (ErrorTypeBlob*)&metadata->data[offset];
+
+ header = (Header *)metadata->data;
+
+ if (!blob->pointer)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Pointer type exected for tag %d", blob->tag);
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_domains; i++)
+ {
+ if (blob->domains[i] == 0 || blob->domains[i] > header->n_entries)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid directory index %d", blob->domains[i]);
+ return FALSE;
+ }
+
+ entry = g_metadata_get_dir_entry (metadata, blob->domains[i]);
+
+ if (entry->blob_type != BLOB_TYPE_ERROR_DOMAIN &&
+ (entry->local || entry->blob_type != BLOB_TYPE_INVALID))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Wrong blob type");
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_type_blob (GMetadata *metadata,
+ guint32 offset,
+ guint32 signature_offset,
+ gboolean return_type,
+ GError **error)
+{
+ SimpleTypeBlob *simple;
+ InterfaceTypeBlob *iface;
+
+ simple = (SimpleTypeBlob *)&metadata->data[offset];
+
+ if (simple->reserved == 0 &&
+ simple->reserved2 == 0)
+ {
+ if (simple->tag >= TYPE_TAG_ARRAY)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Wrong tag in simple type");
+ return FALSE;
+ }
+
+ if (simple->tag >= TYPE_TAG_UTF8 &&
+ !simple->pointer)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Pointer type exected for tag %d", simple->tag);
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ iface = (InterfaceTypeBlob*)&metadata->data[simple->offset];
+
+ switch (iface->tag)
+ {
+ case TYPE_TAG_ARRAY:
+ if (!validate_array_type_blob (metadata, simple->offset,
+ signature_offset, return_type, error))
+ return FALSE;
+ break;
+ case TYPE_TAG_INTERFACE:
+ if (!validate_iface_type_blob (metadata, simple->offset,
+ signature_offset, return_type, error))
+ return FALSE;
+ break;
+ case TYPE_TAG_LIST:
+ case TYPE_TAG_SLIST:
+ if (!validate_param_type_blob (metadata, simple->offset,
+ signature_offset, return_type, 1, error))
+ return FALSE;
+ break;
+ case TYPE_TAG_HASH:
+ if (!validate_param_type_blob (metadata, simple->offset,
+ signature_offset, return_type, 2, error))
+ return FALSE;
+ break;
+ case TYPE_TAG_ERROR:
+ if (!validate_error_type_blob (metadata, simple->offset,
+ signature_offset, return_type, error))
+ return FALSE;
+ break;
+ default:
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Wrong tag in complex type");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_arg_blob (GMetadata *metadata,
+ guint32 offset,
+ guint32 signature_offset,
+ GError **error)
+{
+ ArgBlob *blob;
+
+ if (metadata->len < offset + sizeof (ArgBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (ArgBlob*) &metadata->data[offset];
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid argument name");
+ return FALSE;
+ }
+
+ if (!validate_type_blob (metadata,
+ offset + G_STRUCT_OFFSET (ArgBlob, arg_type),
+ signature_offset, FALSE, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_signature_blob (GMetadata *metadata,
+ guint32 offset,
+ GError **error)
+{
+ SignatureBlob *blob;
+ gint i;
+
+ if (metadata->len < offset + sizeof (SignatureBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (SignatureBlob*) &metadata->data[offset];
+
+ if (blob->return_type.offset != 0)
+ {
+ if (!validate_type_blob (metadata,
+ offset + G_STRUCT_OFFSET (SignatureBlob, return_type),
+ offset, TRUE, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_arguments; i++)
+ {
+ if (!validate_arg_blob (metadata,
+ offset + sizeof (SignatureBlob) +
+ i * sizeof (ArgBlob),
+ offset,
+ error))
+ return FALSE;
+ }
+
+ /* FIXME check constraints on return_value */
+ /* FIXME check array-length pairs */
+ return TRUE;
+}
+
+static gboolean
+validate_function_blob (GMetadata *metadata,
+ guint32 offset,
+ guint16 container_type,
+ GError **error)
+{
+ FunctionBlob *blob;
+
+ if (metadata->len < offset + sizeof (FunctionBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (FunctionBlob*) &metadata->data[offset];
+
+ if (blob->blob_type != BLOB_TYPE_FUNCTION)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Wrong blob type");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid function name");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->symbol))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid function symbol");
+ return FALSE;
+ }
+
+ if (blob->constructor)
+ {
+ switch (container_type)
+ {
+ case BLOB_TYPE_BOXED:
+ case BLOB_TYPE_OBJECT:
+ case BLOB_TYPE_INTERFACE:
+ break;
+ default:
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Constructor not allowed");
+ return FALSE;
+ }
+ }
+
+ if (blob->setter || blob->getter || blob->wraps_vfunc)
+ {
+ switch (container_type)
+ {
+ case BLOB_TYPE_OBJECT:
+ case BLOB_TYPE_INTERFACE:
+ break;
+ default:
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Setter, getter or wrapper not allowed");
+ return FALSE;
+ }
+ }
+
+ if (blob->index)
+ {
+ if (!(blob->setter || blob->getter || blob->wraps_vfunc))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Must be setter, getter or wrapper");
+ return FALSE;
+ }
+ }
+
+ /* FIXME: validate index range */
+ /* FIXME: validate "this" argument for methods */
+ /* FIXME: validate return type for constructors */
+
+ if (!validate_signature_blob (metadata, blob->signature, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_callback_blob (GMetadata *metadata,
+ guint32 offset,
+ GError **error)
+{
+ CallbackBlob *blob;
+
+ if (metadata->len < offset + sizeof (CallbackBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (CallbackBlob*) &metadata->data[offset];
+
+ if (blob->blob_type != BLOB_TYPE_CALLBACK)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Wrong blob type");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid callback name");
+ return FALSE;
+ }
+
+ if (!validate_signature_blob (metadata, blob->signature, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_constant_blob (GMetadata *metadata,
+ guint32 offset,
+ GError **error)
+{
+ gint value_size[] = {
+ 0, 4, 1, 1, 2, 2, 4, 4, 8, 8,
+ sizeof (gint), sizeof (guint),
+ sizeof (glong), sizeof (gulong),
+ sizeof (gssize), sizeof (gsize),
+ sizeof (gfloat), sizeof (gdouble),
+ 0, 0
+ };
+ ConstantBlob *blob;
+ SimpleTypeBlob *type;
+
+ if (metadata->len < offset + sizeof (ConstantBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (ConstantBlob*) &metadata->data[offset];
+
+ if (blob->blob_type != BLOB_TYPE_CONSTANT)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Wrong blob type");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid constant name");
+ return FALSE;
+ }
+
+ if (!validate_type_blob (metadata, offset + G_STRUCT_OFFSET (ConstantBlob, type),
+ 0, FALSE, error))
+ return FALSE;
+
+ if (!is_aligned (blob->offset))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Misaligned constant value");
+ return FALSE;
+ }
+
+ type = (SimpleTypeBlob *)&metadata->data[offset + G_STRUCT_OFFSET (ConstantBlob, type)];
+ if (type->reserved == 0)
+ {
+ if (type->tag == 0)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Constant value type void");
+ return FALSE;
+ }
+
+ if (value_size[type->tag] != 0 &&
+ blob->size != value_size[type->tag])
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Constant value size mismatch");
+ return FALSE;
+ }
+ /* FIXME check string values */
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_value_blob (GMetadata *metadata,
+ guint32 offset,
+ GError **error)
+{
+ ValueBlob *blob;
+
+ if (metadata->len < offset + sizeof (ValueBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (ValueBlob*) &metadata->data[offset];
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid value name");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_field_blob (GMetadata *metadata,
+ guint32 offset,
+ GError **error)
+{
+ FieldBlob *blob;
+
+ if (metadata->len < offset + sizeof (FieldBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (FieldBlob*) &metadata->data[offset];
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid field name");
+ return FALSE;
+ }
+
+ if (!validate_type_blob (metadata,
+ offset + G_STRUCT_OFFSET (FieldBlob, type),
+ 0, FALSE, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_property_blob (GMetadata *metadata,
+ guint32 offset,
+ GError **error)
+{
+ PropertyBlob *blob;
+
+ if (metadata->len < offset + sizeof (PropertyBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (PropertyBlob*) &metadata->data[offset];
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid property name");
+ return FALSE;
+ }
+
+ if (!validate_type_blob (metadata,
+ offset + G_STRUCT_OFFSET (PropertyBlob, type),
+ 0, FALSE, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_signal_blob (GMetadata *metadata,
+ guint32 offset,
+ guint32 container_offset,
+ GError **error)
+{
+ SignalBlob *blob;
+ gint n_signals;
+
+ if (metadata->len < offset + sizeof (SignalBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (SignalBlob*) &metadata->data[offset];
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid signal name");
+ return FALSE;
+ }
+
+ if ((blob->run_first != 0) +
+ (blob->run_last != 0) +
+ (blob->run_cleanup != 0) != 1)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid signal run flags");
+ return FALSE;
+ }
+
+ if (blob->has_class_closure)
+ {
+ if (((CommonBlob*)&metadata->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
+ {
+ ObjectBlob *object;
+
+ object = (ObjectBlob*)&metadata->data[container_offset];
+
+ n_signals = object->n_signals;
+ }
+ else
+ {
+ InterfaceBlob *iface;
+
+ iface = (InterfaceBlob*)&metadata->data[container_offset];
+
+ n_signals = iface->n_signals;
+ }
+
+ if (blob->class_closure >= n_signals)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid class closure index");
+ return FALSE;
+ }
+ }
+
+ if (!validate_signature_blob (metadata, blob->signature, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_vfunc_blob (GMetadata *metadata,
+ guint32 offset,
+ guint32 container_offset,
+ GError **error)
+{
+ VFuncBlob *blob;
+ gint n_vfuncs;
+
+ if (metadata->len < offset + sizeof (VFuncBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (VFuncBlob*) &metadata->data[offset];
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid vfunc name");
+ return FALSE;
+ }
+
+ if (blob->class_closure)
+ {
+ if (((CommonBlob*)&metadata->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
+ {
+ ObjectBlob *object;
+
+ object = (ObjectBlob*)&metadata->data[container_offset];
+
+ n_vfuncs = object->n_vfuncs;
+ }
+ else
+ {
+ InterfaceBlob *iface;
+
+ iface = (InterfaceBlob*)&metadata->data[container_offset];
+
+ n_vfuncs = iface->n_vfuncs;
+ }
+
+ if (blob->class_closure >= n_vfuncs)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid class closure index");
+ return FALSE;
+ }
+ }
+
+ if (!validate_signature_blob (metadata, blob->signature, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_struct_blob (GMetadata *metadata,
+ guint32 offset,
+ guint16 blob_type,
+ GError **error)
+{
+ StructBlob *blob;
+ gint i;
+
+ if (metadata->len < offset + sizeof (StructBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (StructBlob*) &metadata->data[offset];
+
+ if (blob->blob_type != blob_type)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Wrong blob type");
+ return FALSE;
+ }
+
+ if ((blob->blob_type == BLOB_TYPE_BOXED && blob->unregistered) ||
+ (blob->blob_type == BLOB_TYPE_STRUCT && !blob->unregistered))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Registration/blob type mismatch");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid struct name");
+ return FALSE;
+ }
+
+ if (blob_type == BLOB_TYPE_BOXED)
+ {
+ if (!is_name (metadata->data, blob->gtype_name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid boxed type name");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->gtype_init))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid boxed type init");
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (blob->gtype_name || blob->gtype_init)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Gtype data in struct");
+ return FALSE;
+ }
+ }
+
+ if (metadata->len < offset + sizeof (StructBlob) +
+ blob->n_fields * sizeof (FieldBlob) +
+ blob->n_methods * sizeof (FunctionBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_fields; i++)
+ {
+ if (!validate_field_blob (metadata,
+ offset + sizeof (StructBlob) +
+ i * sizeof (FieldBlob),
+ error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_methods; i++)
+ {
+ if (!validate_function_blob (metadata,
+ offset + sizeof (StructBlob) +
+ blob->n_fields * sizeof (FieldBlob) +
+ i * sizeof (FunctionBlob),
+ blob_type,
+ error))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_enum_blob (GMetadata *metadata,
+ guint32 offset,
+ guint16 blob_type,
+ GError **error)
+{
+ EnumBlob *blob;
+ ValueBlob *v1, *v2;
+ gint i, j;
+
+ if (metadata->len < offset + sizeof (EnumBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (EnumBlob*) &metadata->data[offset];
+
+ if (blob->blob_type != blob_type)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Wrong blob type");
+ return FALSE;
+ }
+
+ if (!blob->unregistered)
+ {
+ if (!is_name (metadata->data, blob->gtype_name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid enum type name");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->gtype_init))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid enum type init");
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (blob->gtype_name || blob->gtype_init)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Gtype data in unregistered enum");
+ return FALSE;
+ }
+ }
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid enum name");
+ return FALSE;
+ }
+
+ if (metadata->len < offset + sizeof (EnumBlob) +
+ blob->n_values * sizeof (ValueBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_values; i++)
+ {
+ if (!validate_value_blob (metadata,
+ offset + sizeof (EnumBlob) +
+ i * sizeof (ValueBlob),
+ error))
+ return FALSE;
+
+ v1 = (ValueBlob *)&metadata->data[offset + sizeof (EnumBlob) +
+ i * sizeof (ValueBlob)];
+ for (j = 0; j < i; j++)
+ {
+ v2 = (ValueBlob *)&metadata->data[offset + sizeof (EnumBlob) +
+ j * sizeof (ValueBlob)];
+
+ if (v1->value == v2->value)
+ {
+ /* FIXME should this be an error ? */
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Duplicate enum value");
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_object_blob (GMetadata *metadata,
+ guint32 offset,
+ GError **error)
+{
+ Header *header;
+ ObjectBlob *blob;
+ gint i;
+ guint32 offset2;
+
+ header = (Header *)metadata->data;
+
+ if (metadata->len < offset + sizeof (ObjectBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (ObjectBlob*) &metadata->data[offset];
+
+ if (blob->blob_type != BLOB_TYPE_OBJECT)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Wrong blob type");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->gtype_name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid object type name");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->gtype_init))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid object type init");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid object name");
+ return FALSE;
+ }
+
+ if (blob->parent > header->n_entries)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid parent index");
+ return FALSE;
+ }
+
+ if (blob->parent != 0)
+ {
+ DirEntry *entry;
+
+ entry = g_metadata_get_dir_entry (metadata, blob->parent);
+ if (entry->blob_type != BLOB_TYPE_OBJECT &&
+ (entry->local || entry->blob_type != 0))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Parent not object");
+ return FALSE;
+ }
+ }
+
+ if (metadata->len < offset + sizeof (ObjectBlob) +
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2 +
+ blob->n_fields * sizeof (FieldBlob) +
+ blob->n_properties * sizeof (PropertyBlob) +
+ blob->n_methods * sizeof (FunctionBlob) +
+ blob->n_signals * sizeof (SignalBlob) +
+ blob->n_vfuncs * sizeof (VFuncBlob) +
+ blob->n_constants * sizeof (ConstantBlob))
+
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ offset2 = offset + sizeof (ObjectBlob);
+
+ for (i = 0; i < blob->n_interfaces; i++, offset2 += 2)
+ {
+ guint16 iface;
+ DirEntry *entry;
+
+ iface = *(guint16*)&metadata->data[offset2];
+ if (iface == 0 || iface > header->n_entries)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid interface index");
+ return FALSE;
+ }
+
+ entry = g_metadata_get_dir_entry (metadata, iface);
+
+ if (entry->blob_type != BLOB_TYPE_INTERFACE &&
+ (entry->local || entry->blob_type != 0))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Not an interface");
+ return FALSE;
+ }
+ }
+
+ offset2 += 2 * (blob->n_interfaces %2);
+
+ for (i = 0; i < blob->n_fields; i++, offset2 += sizeof (FieldBlob))
+ {
+ if (!validate_field_blob (metadata, offset2, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
+ {
+ if (!validate_property_blob (metadata, offset2, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
+ {
+ if (!validate_function_blob (metadata, offset2, BLOB_TYPE_OBJECT, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
+ {
+ if (!validate_signal_blob (metadata, offset2, offset, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
+ {
+ if (!validate_vfunc_blob (metadata, offset2, offset, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
+ {
+ if (!validate_constant_blob (metadata, offset2, error))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_interface_blob (GMetadata *metadata,
+ guint32 offset,
+ GError **error)
+{
+ Header *header;
+ InterfaceBlob *blob;
+ gint i;
+ guint32 offset2;
+
+ header = (Header *)metadata->data;
+
+ if (metadata->len < offset + sizeof (InterfaceBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (InterfaceBlob*) &metadata->data[offset];
+
+ if (blob->blob_type != BLOB_TYPE_INTERFACE)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Wrong blob type");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->gtype_name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid interface type name");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->gtype_init))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid interface type init");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid interface name");
+ return FALSE;
+ }
+
+ if (metadata->len < offset + sizeof (InterfaceBlob) +
+ (blob->n_prerequisites + blob->n_prerequisites % 2) * 2 +
+ blob->n_properties * sizeof (PropertyBlob) +
+ blob->n_methods * sizeof (FunctionBlob) +
+ blob->n_signals * sizeof (SignalBlob) +
+ blob->n_vfuncs * sizeof (VFuncBlob) +
+ blob->n_constants * sizeof (ConstantBlob))
+
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ offset2 = offset + sizeof (InterfaceBlob);
+
+ for (i = 0; i < blob->n_prerequisites; i++, offset2 += 2)
+ {
+ DirEntry *entry;
+ guint16 req;
+
+ req = *(guint16*)&metadata->data[offset2];
+ if (req == 0 || req > header->n_entries)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Invalid prerequisite index");
+ return FALSE;
+ }
+
+ entry = g_metadata_get_dir_entry (metadata, req);
+ if (entry->blob_type != BLOB_TYPE_INTERFACE &&
+ entry->blob_type != BLOB_TYPE_OBJECT &&
+ (entry->local || entry->blob_type != 0))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_BLOB,
+ "Not an interface or object");
+ return FALSE;
+ }
+ }
+
+ offset2 += 2 * (blob->n_prerequisites % 2);
+
+ for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
+ {
+ if (!validate_property_blob (metadata, offset2, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
+ {
+ if (!validate_function_blob (metadata, offset2, BLOB_TYPE_INTERFACE, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
+ {
+ if (!validate_signal_blob (metadata, offset2, offset, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
+ {
+ if (!validate_vfunc_blob (metadata, offset2, offset, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
+ {
+ if (!validate_constant_blob (metadata, offset2, error))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_errordomain_blob (GMetadata *metadata,
+ guint32 offset,
+ GError **error)
+{
+ return TRUE;
+}
+
+static gboolean
+validate_union_blob (GMetadata *metadata,
+ guint32 offset,
+ GError **error)
+{
+ return TRUE;
+}
+
+static gboolean
+validate_blob (GMetadata *metadata,
+ guint32 offset,
+ GError **error)
+{
+ CommonBlob *common;
+
+ if (metadata->len < offset + sizeof (CommonBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ common = (CommonBlob*)&metadata->data[offset];
+
+ switch (common->blob_type)
+ {
+ case BLOB_TYPE_FUNCTION:
+ if (!validate_function_blob (metadata, offset, 0, error))
+ return FALSE;
+ break;
+ case BLOB_TYPE_CALLBACK:
+ if (!validate_callback_blob (metadata, offset, error))
+ return FALSE;
+ break;
+ case BLOB_TYPE_STRUCT:
+ case BLOB_TYPE_BOXED:
+ if (!validate_struct_blob (metadata, offset, common->blob_type, error))
+ return FALSE;
+ break;
+ case BLOB_TYPE_ENUM:
+ case BLOB_TYPE_FLAGS:
+ if (!validate_enum_blob (metadata, offset, common->blob_type, error))
+ return FALSE;
+ break;
+ case BLOB_TYPE_OBJECT:
+ if (!validate_object_blob (metadata, offset, error))
+ return FALSE;
+ break;
+ case BLOB_TYPE_INTERFACE:
+ if (!validate_interface_blob (metadata, offset, error))
+ return FALSE;
+ break;
+ case BLOB_TYPE_CONSTANT:
+ if (!validate_constant_blob (metadata, offset, error))
+ return FALSE;
+ break;
+ case BLOB_TYPE_ERROR_DOMAIN:
+ if (!validate_errordomain_blob (metadata, offset, error))
+ return FALSE;
+ break;
+ case BLOB_TYPE_UNION:
+ if (!validate_union_blob (metadata, offset, error))
+ return FALSE;
+ break;
+ default:
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_ENTRY,
+ "Invalid blob type");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_directory (GMetadata *metadata,
+ GError **error)
+{
+ Header *header = (Header *)metadata->data;
+ DirEntry *entry;
+ gint i;
+
+ if (metadata->len < header->directory + header->n_entries * sizeof (DirEntry))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ for (i = 0; i < header->n_entries; i++)
+ {
+ entry = g_metadata_get_dir_entry (metadata, i + 1);
+
+ if (!is_name (metadata->data, entry->name))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_DIRECTORY,
+ "Invalid entry name");
+ return FALSE;
+ }
+
+ if ((entry->local && entry->blob_type == BLOB_TYPE_INVALID) ||
+ entry->blob_type > BLOB_TYPE_UNION)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_DIRECTORY,
+ "Invalid entry type");
+ return FALSE;
+ }
+
+ if (i < header->n_local_entries)
+ {
+ if (!entry->local)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_DIRECTORY,
+ "Too few local directory entries");
+ return FALSE;
+ }
+
+ if (!is_aligned (entry->offset))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_DIRECTORY,
+ "Misaligned entry");
+ return FALSE;
+ }
+
+ if (!validate_blob (metadata, entry->offset, error))
+ return FALSE;
+ }
+ else
+ {
+ if (entry->local)
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_DIRECTORY,
+ "Too many local directory entries");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, entry->offset))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID_DIRECTORY,
+ "Invalid namespace name");
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_annotations (GMetadata *metadata,
+ GError **error)
+{
+ Header *header = (Header *)metadata->data;
+
+ if (header->size < header->annotations + header->n_annotations * sizeof (AnnotationBlob))
+ {
+ g_set_error (error,
+ G_METADATA_ERROR,
+ G_METADATA_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+g_metadata_validate (GMetadata *metadata,
+ GError **error)
+{
+ if (!validate_header (metadata, error))
+ return FALSE;
+
+ if (!validate_directory (metadata, error))
+ return FALSE;
+
+ if (!validate_annotations (metadata, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+GQuark
+g_metadata_error_quark (void)
+{
+ static GQuark quark = 0;
+ if (quark == 0)
+ quark = g_quark_from_static_string ("g-metadata-error-quark");
+ return quark;
+}
+
+
+static inline void
+_g_metadata_init (GMetadata *metadata)
+{
+ Header *header;
+
+ header = (Header *) metadata->data;
+ if (header->shared_library)
+ {
+ const gchar *shlib;
+ shlib = g_metadata_get_string (metadata, header->shared_library);
+ metadata->module = g_module_open (shlib, G_MODULE_BIND_LAZY|G_MODULE_BIND_LOCAL);
+ if (metadata->module == NULL)
+ g_warning ("Failed to load shared library referenced by the metadata: %s",
+ g_module_error ());
+ }
+}
+
+/**
+ * g_metadata_new_from_memory:
+ * @memory: address of memory chunk containing the metadata
+ * @len: length of memory chunk containing the metadata
+ *
+ * Creates a new #GMetadata from a memory location. The memory block
+ * pointed to by @metadata will be automatically g_free()d when the
+ * repository is destroyed.
+ *
+ * Return value: the new #GMetadata
+ **/
+GMetadata *
+g_metadata_new_from_memory (guchar *memory, gsize len)
+{
+ GMetadata *meta;
+
+ meta = g_new0 (GMetadata, 1);
+ meta->data = memory;
+ meta->len = len;
+ meta->owns_memory = TRUE;
+ _g_metadata_init (meta);
+ return meta;
+}
+
+/**
+ * g_metadata_new_from_const_memory:
+ * @memory: address of memory chunk containing the metadata
+ * @len: length of memory chunk containing the metadata
+ *
+ * Creates a new #GMetadata from a memory location.
+ *
+ * Return value: the new #GMetadata
+ **/
+GMetadata *
+g_metadata_new_from_const_memory (const guchar *memory, gsize len)
+{
+ GMetadata *meta;
+
+ meta = g_new0 (GMetadata, 1);
+ meta->data = (guchar *) memory;
+ meta->len = len;
+ meta->owns_memory = FALSE;
+ _g_metadata_init (meta);
+ return meta;
+}
+
+/**
+ * g_metadata_new_from_mapped_file:
+ * @mfile: a #GMappedFile, that will be free'd when the repository is destroyed
+ *
+ * Creates a new #GMetadata from a #GMappedFile.
+ *
+ * Return value: the new #GMetadata
+ **/
+GMetadata *
+g_metadata_new_from_mapped_file (GMappedFile *mfile)
+{
+ GMetadata *meta;
+
+ meta = g_new0 (GMetadata, 1);
+ meta->mfile = mfile;
+ meta->owns_memory = FALSE;
+ meta->data = (guchar *) g_mapped_file_get_contents (mfile);
+ meta->len = g_mapped_file_get_length (mfile);
+ _g_metadata_init (meta);
+ return meta;
+}
+
+/**
+ * g_metadata_free:
+ * @metadata: a #GMetadata
+ *
+ * Free a #GMetadata.
+ **/
+void
+g_metadata_free (GMetadata *metadata)
+{
+ if (metadata->mfile)
+ g_mapped_file_free (metadata->mfile);
+ else
+ if (metadata->owns_memory)
+ g_free (metadata->data);
+ if (metadata->module)
+ g_module_close (metadata->module);
+ g_free (metadata);
+}
+
+/**
+ * g_metadata_set_module:
+ * @metadata: a #GMetadata instance
+ * @module: a #GModule; takes ownership of this module
+ *
+ * Sets the target module for all symbols referenced by the metadata.
+ **/
+void
+g_metadata_set_module (GMetadata *metadata, GModule *module)
+{
+ if (metadata->module)
+ g_module_close (metadata->module);
+ metadata->module = module;
+}
+
+const gchar *
+g_metadata_get_namespace(GMetadata *metadata)
+{
+ return g_metadata_get_string (metadata, ((Header *) metadata->data)->namespace);
+}
diff --git a/gobject-introspection/gmetadata.h b/gobject-introspection/gmetadata.h
index 7ca390c0d..a22ee235e 100644
--- a/gobject-introspection/gmetadata.h
+++ b/gobject-introspection/gmetadata.h
@@ -22,6 +22,9 @@
#ifndef __G_METADATA_H__
#define __G_METADATA_H__
+#include <gmodule.h>
+#include "girepository.h"
+
G_BEGIN_DECLS
#define G_IDL_MAGIC "GOBJ\nMETADATA\r\n\032"
@@ -56,6 +59,7 @@ typedef struct
guint32 size;
guint32 namespace;
+ guint32 shared_library;
guint16 entry_blob_size;
guint16 function_blob_size;
@@ -77,7 +81,7 @@ typedef struct
guint16 interface_blob_size;
guint16 union_blob_size;
- guint16 padding;
+ guint16 padding[7];
} Header;
typedef struct
@@ -506,13 +510,20 @@ typedef struct
} AnnotationBlob;
+struct _GMetadata {
+ guchar *data;
+ gsize len;
+ gboolean owns_memory;
+ GMappedFile *mfile;
+ GModule *module;
+};
-DirEntry *g_metadata_get_dir_entry (const guchar *metadata,
- guint16 index);
+DirEntry *g_metadata_get_dir_entry (GMetadata *metadata,
+ guint16 index);
void g_metadata_check_sanity (void);
-#define g_metadata_get_string(metadata,offset) ((const gchar*)&(metadata)[(offset)])
+#define g_metadata_get_string(metadata,offset) ((const gchar*)&(metadata->data)[(offset)])
typedef enum
@@ -528,9 +539,8 @@ typedef enum
GQuark g_metadata_error_quark (void);
-gboolean g_metadata_validate (const guchar *data,
- guint len,
- GError **error);
+gboolean g_metadata_validate (GMetadata *metadata,
+ GError **error);
G_END_DECLS
diff --git a/gobject-introspection/scanner.c b/gobject-introspection/scanner.c
new file mode 100644
index 000000000..58885791a
--- /dev/null
+++ b/gobject-introspection/scanner.c
@@ -0,0 +1,1824 @@
+/* GObject introspection: scanner
+ *
+ * Copyright (C) 2007-2008 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 <j@bitron.ch>
+ */
+
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib-object.h>
+#include <sys/wait.h> /* waitpid */
+#include <gmodule.h>
+#include "scanner.h"
+#include "gidlparser.h"
+#include "gidlmodule.h"
+#include "gidlnode.h"
+#include "gidlwriter.h"
+
+typedef GType (*TypeFunction) (void);
+
+static void g_igenerator_parse_macros (GIGenerator * igenerator);
+
+static int
+g_idl_node_cmp (GIdlNode * a, GIdlNode * b)
+{
+ if (a->type < b->type)
+ {
+ return -1;
+ }
+ else if (a->type > b->type)
+ {
+ return 1;
+ }
+ else
+ {
+ return strcmp (a->name, b->name);
+ }
+}
+
+static GIGenerator *
+g_igenerator_new (const gchar *namespace,
+ const gchar *shared_library)
+{
+ GIGenerator *igenerator = g_new0 (GIGenerator, 1);
+ igenerator->namespace = g_strdup (namespace);
+ igenerator->shared_library = g_strdup (shared_library);
+ igenerator->lower_case_namespace =
+ g_ascii_strdown (igenerator->namespace, -1);
+ igenerator->module = g_idl_module_new (namespace, shared_library);
+
+ igenerator->typedef_table = g_hash_table_new (g_str_hash, g_str_equal);
+ igenerator->struct_or_union_or_enum_table =
+ g_hash_table_new (g_str_hash, g_str_equal);
+
+ igenerator->type_map = g_hash_table_new (g_str_hash, g_str_equal);
+ igenerator->type_by_lower_case_prefix =
+ g_hash_table_new (g_str_hash, g_str_equal);
+ igenerator->symbols = g_hash_table_new (g_str_hash, g_str_equal);
+
+ return igenerator;
+}
+
+static void
+g_igenerator_free (GIGenerator *generator)
+{
+ g_free (generator->namespace);
+ g_free (generator->shared_library);
+ g_free (generator->lower_case_namespace);
+#if 0
+ g_idl_module_free (generator->module);
+#endif
+ g_hash_table_destroy (generator->typedef_table);
+ g_hash_table_destroy (generator->struct_or_union_or_enum_table);
+ g_hash_table_destroy (generator->type_map);
+ g_hash_table_destroy (generator->type_by_lower_case_prefix);
+ g_hash_table_destroy (generator->symbols);
+ g_list_foreach (generator->filenames, (GFunc)g_free, NULL);
+ g_list_free (generator->filenames);
+#if 0
+ g_list_foreach (generator->symbol_list, (GFunc)csymbol_free, NULL);
+ g_list_free (generator->symbol_list);
+#endif
+ g_free (generator);
+}
+
+static GIdlNodeType *
+get_type_from_type_id (GType type_id)
+{
+ GIdlNodeType *gitype = (GIdlNodeType *) g_idl_node_new (G_IDL_NODE_TYPE);
+
+ GType type_fundamental = g_type_fundamental (type_id);
+
+ if (type_fundamental == G_TYPE_STRING)
+ {
+ gitype->unparsed = g_strdup ("char*");
+ }
+ else if (type_id == G_TYPE_STRV)
+ {
+ gitype->unparsed = g_strdup ("char*[]");
+ }
+ else if (type_fundamental == G_TYPE_INTERFACE
+ || type_fundamental == G_TYPE_BOXED
+ || type_fundamental == G_TYPE_OBJECT)
+ {
+ gitype->unparsed = g_strdup_printf ("%s*", g_type_name (type_id));
+ }
+ else if (type_fundamental == G_TYPE_PARAM)
+ {
+ gitype->unparsed = g_strdup ("GParamSpec*");
+ }
+ else
+ {
+ gitype->unparsed = g_strdup (g_type_name (type_id));
+ }
+
+ return gitype;
+}
+
+static char *
+str_replace (const char *str, const char *needle, const char *replacement)
+{
+ char **strings = g_strsplit (str, needle, 0);
+ char *result = g_strjoinv (replacement, strings);
+ g_strfreev (strings);
+ return result;
+}
+
+static void
+g_igenerator_process_properties (GIGenerator * igenerator,
+ GIdlNodeInterface * ginode, GType type_id)
+{
+ int i;
+ guint n_properties;
+ GParamSpec **properties;
+
+ if (ginode->node.type == G_IDL_NODE_OBJECT)
+ {
+ GObjectClass *type_class = g_type_class_ref (type_id);
+ properties = g_object_class_list_properties (type_class, &n_properties);
+ }
+ else if (ginode->node.type == G_IDL_NODE_INTERFACE)
+ {
+ GTypeInterface *iface = g_type_default_interface_ref (type_id);
+ properties = g_object_interface_list_properties (iface, &n_properties);
+ }
+ else
+ {
+ g_assert_not_reached ();
+ }
+
+ for (i = 0; i < n_properties; i++)
+ {
+ GIdlNodeProperty *giprop;
+
+ /* ignore inherited properties */
+ if (properties[i]->owner_type != type_id)
+ {
+ continue;
+ }
+ giprop = (GIdlNodeProperty *) g_idl_node_new (G_IDL_NODE_PROPERTY);
+ giprop->node.name = properties[i]->name;
+ ginode->members =
+ g_list_insert_sorted (ginode->members, giprop,
+ (GCompareFunc) g_idl_node_cmp);
+ giprop->type = get_type_from_type_id (properties[i]->value_type);
+ giprop->readable = (properties[i]->flags & G_PARAM_READABLE) != 0;
+ giprop->writable = (properties[i]->flags & G_PARAM_WRITABLE) != 0;
+ giprop->construct = (properties[i]->flags & G_PARAM_CONSTRUCT) != 0;
+ giprop->construct_only =
+ (properties[i]->flags & G_PARAM_CONSTRUCT_ONLY) != 0;
+ }
+}
+
+static void
+g_igenerator_process_signals (GIGenerator * igenerator,
+ GIdlNodeInterface * ginode, GType type_id)
+{
+ int i, j;
+ guint n_signal_ids;
+ guint *signal_ids = g_signal_list_ids (type_id, &n_signal_ids);
+
+ for (i = 0; i < n_signal_ids; i++)
+ {
+ GSignalQuery signal_query;
+ GIdlNodeSignal *gisig;
+ GIdlNodeParam *giparam;
+
+ g_signal_query (signal_ids[i], &signal_query);
+ gisig = (GIdlNodeSignal *) g_idl_node_new (G_IDL_NODE_SIGNAL);
+ gisig->node.name = g_strdup (signal_query.signal_name);
+ ginode->members =
+ g_list_insert_sorted (ginode->members, gisig,
+ (GCompareFunc) g_idl_node_cmp);
+
+ gisig->run_first =
+ (signal_query.signal_flags & G_SIGNAL_RUN_FIRST) != 0;
+ gisig->run_last = (signal_query.signal_flags & G_SIGNAL_RUN_LAST) != 0;
+ gisig->run_cleanup =
+ (signal_query.signal_flags & G_SIGNAL_RUN_CLEANUP) != 0;
+
+ /* add sender parameter */
+ giparam = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+ gisig->parameters = g_list_append (gisig->parameters, giparam);
+ giparam->node.name = g_strdup ("object");
+ giparam->type = get_type_from_type_id (type_id);
+
+ for (j = 0; j < signal_query.n_params; j++)
+ {
+ giparam = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+ gisig->parameters = g_list_append (gisig->parameters, giparam);
+ giparam->node.name = g_strdup_printf ("p%d", j);
+ giparam->type = get_type_from_type_id (signal_query.param_types[j]);
+ }
+ gisig->result = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+ gisig->result->type = get_type_from_type_id (signal_query.return_type);
+ }
+}
+
+static const gchar *
+lookup_symbol (GIGenerator *igenerator, const gchar *typename)
+{
+ const gchar *name =
+ g_hash_table_lookup (igenerator->symbols, typename);
+
+ if (!name)
+ {
+ g_printerr ("Unknown symbol: %s\n", typename);
+ return typename;
+ }
+
+ return name;
+}
+
+static void
+g_igenerator_create_object (GIGenerator *igenerator,
+ const char *symbol_name,
+ GType type_id,
+ char *lower_case_prefix)
+
+{
+ char *alt_lower_case_prefix;
+ GIdlNodeInterface *ginode;
+ guint n_type_interfaces;
+ GType *type_interfaces;
+ int i;
+
+ ginode = (GIdlNodeInterface *) g_idl_node_new (G_IDL_NODE_OBJECT);
+ ginode->node.name = g_strdup (g_type_name (type_id));
+ igenerator->module->entries =
+ g_list_insert_sorted (igenerator->module->entries, ginode,
+ (GCompareFunc) g_idl_node_cmp);
+ g_hash_table_insert (igenerator->type_map, ginode->node.name,
+ ginode);
+ g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+ lower_case_prefix, ginode);
+ alt_lower_case_prefix = g_ascii_strdown (ginode->node.name, -1);
+
+ if (strcmp (alt_lower_case_prefix, lower_case_prefix) != 0)
+ {
+ /* alternative prefix sometimes necessary, for example
+ * for GdkWindow
+ */
+ g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+ alt_lower_case_prefix, ginode);
+ }
+ else
+ {
+ g_free (alt_lower_case_prefix);
+ }
+
+ ginode->gtype_name = ginode->node.name;
+ ginode->gtype_init = g_strdup (symbol_name);
+ ginode->parent = g_strdup (lookup_symbol (igenerator,
+ g_type_name (g_type_parent (type_id))));
+
+ type_interfaces = g_type_interfaces (type_id, &n_type_interfaces);
+ for (i = 0; i < n_type_interfaces; i++)
+ {
+ char *iface_name =
+ g_strdup (g_type_name (type_interfaces[i]));
+ /* workaround for AtkImplementorIface */
+ if (g_str_has_suffix (iface_name, "Iface"))
+ {
+ iface_name[strlen (iface_name) - strlen ("Iface")] =
+ '\0';
+ }
+ ginode->interfaces =
+ g_list_append (ginode->interfaces, iface_name);
+ }
+
+ g_hash_table_insert (igenerator->symbols,
+ g_strdup (ginode->gtype_name),
+ /* FIXME: Strip igenerator->namespace */
+ g_strdup (ginode->node.name));
+
+ g_igenerator_process_properties (igenerator, ginode, type_id);
+ g_igenerator_process_signals (igenerator, ginode, type_id);
+}
+
+static void
+g_igenerator_create_interface (GIGenerator *igenerator,
+ const char *symbol_name,
+ GType type_id,
+ char *lower_case_prefix)
+
+{
+ GIdlNodeInterface *ginode;
+ gboolean is_gobject = FALSE;
+ guint n_iface_prereqs;
+ GType *iface_prereqs;
+ int i;
+
+ ginode = (GIdlNodeInterface *) g_idl_node_new (G_IDL_NODE_INTERFACE);
+ ginode->node.name = g_strdup (g_type_name (type_id));
+
+ /* workaround for AtkImplementorIface */
+ if (g_str_has_suffix (ginode->node.name, "Iface"))
+ {
+ ginode->node.name[strlen (ginode->node.name) -
+ strlen ("Iface")] = '\0';
+ }
+ igenerator->module->entries =
+ g_list_insert_sorted (igenerator->module->entries, ginode,
+ (GCompareFunc) g_idl_node_cmp);
+ g_hash_table_insert (igenerator->type_map, ginode->node.name,
+ ginode);
+ g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+ lower_case_prefix, ginode);
+ ginode->gtype_name = ginode->node.name;
+ ginode->gtype_init = g_strdup (symbol_name);
+
+ iface_prereqs =
+ g_type_interface_prerequisites (type_id, &n_iface_prereqs);
+
+ for (i = 0; i < n_iface_prereqs; i++)
+ {
+ if (g_type_fundamental (iface_prereqs[i]) == G_TYPE_OBJECT)
+ {
+ is_gobject = TRUE;
+ }
+ ginode->prerequisites =
+ g_list_append (ginode->prerequisites,
+ g_strdup (g_type_name (iface_prereqs[i])));
+ }
+
+ if (is_gobject)
+ g_igenerator_process_properties (igenerator, ginode, type_id);
+ else
+ g_type_default_interface_ref (type_id);
+
+ g_igenerator_process_signals (igenerator, ginode, type_id);
+}
+
+static void
+g_igenerator_create_boxed (GIGenerator *igenerator,
+ const char *symbol_name,
+ GType type_id,
+ char *lower_case_prefix)
+{
+ GIdlNodeBoxed *ginode =
+ (GIdlNodeBoxed *) g_idl_node_new (G_IDL_NODE_BOXED);
+ ginode->node.name = g_strdup (g_type_name (type_id));
+ igenerator->module->entries =
+ g_list_insert_sorted (igenerator->module->entries, ginode,
+ (GCompareFunc) g_idl_node_cmp);
+ g_hash_table_insert (igenerator->type_map, ginode->node.name,
+ ginode);
+ g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+ lower_case_prefix, ginode);
+ ginode->gtype_name = ginode->node.name;
+ ginode->gtype_init = g_strdup (symbol_name);
+}
+
+static void
+g_igenerator_create_enum (GIGenerator *igenerator,
+ const char *symbol_name,
+ GType type_id,
+ char *lower_case_prefix)
+{
+ GIdlNodeEnum *ginode;
+ int i;
+ GEnumClass *type_class;
+
+ ginode = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_ENUM);
+ ginode->node.name = g_strdup (g_type_name (type_id));
+ igenerator->module->entries =
+ g_list_insert_sorted (igenerator->module->entries, ginode,
+ (GCompareFunc) g_idl_node_cmp);
+ g_hash_table_insert (igenerator->type_map, ginode->node.name,
+ ginode);
+ g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+ lower_case_prefix, ginode);
+ ginode->gtype_name = ginode->node.name;
+ ginode->gtype_init = g_strdup (symbol_name);
+
+ type_class = g_type_class_ref (type_id);
+
+ for (i = 0; i < type_class->n_values; i++)
+ {
+ GIdlNodeValue *gival =
+ (GIdlNodeValue *) g_idl_node_new (G_IDL_NODE_VALUE);
+ ginode->values = g_list_append (ginode->values, gival);
+ gival->node.name =
+ g_strdup (type_class->values[i].value_name);
+ gival->value = type_class->values[i].value;
+ }
+}
+
+static void
+g_igenerator_create_flags (GIGenerator *igenerator,
+ const char *symbol_name,
+ GType type_id,
+ char *lower_case_prefix)
+{
+ GIdlNodeEnum *ginode;
+ GFlagsClass *type_class;
+ int i;
+
+ ginode = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_FLAGS);
+ ginode->node.name = g_strdup (g_type_name (type_id));
+ igenerator->module->entries =
+ g_list_insert_sorted (igenerator->module->entries, ginode,
+ (GCompareFunc) g_idl_node_cmp);
+ g_hash_table_insert (igenerator->type_map, ginode->node.name,
+ ginode);
+ g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+ lower_case_prefix, ginode);
+ ginode->gtype_name = ginode->node.name;
+ ginode->gtype_init = g_strdup (symbol_name);
+
+ type_class = g_type_class_ref (type_id);
+
+ for (i = 0; i < type_class->n_values; i++)
+ {
+ GIdlNodeValue *gival =
+ (GIdlNodeValue *) g_idl_node_new (G_IDL_NODE_VALUE);
+ ginode->values = g_list_append (ginode->values, gival);
+ gival->node.name =
+ g_strdup (type_class->values[i].value_name);
+ gival->value = type_class->values[i].value;
+ }
+}
+
+static gboolean
+g_igenerator_process_module_symbol (GIGenerator *igenerator,
+ GModule *module,
+ const gchar *symbol_name)
+{
+ TypeFunction type_fun;
+ GType type_id;
+ GType type_fundamental;
+ char *lower_case_prefix;
+
+ /* ignore already processed functions */
+ if (symbol_name == NULL)
+ return FALSE;
+
+ if (!g_module_symbol (module,
+ symbol_name,
+ (gpointer *) & type_fun))
+ return FALSE;
+
+ type_id = type_fun ();
+ type_fundamental = g_type_fundamental (type_id);
+ lower_case_prefix =
+ str_replace (g_strndup
+ (symbol_name,
+ strlen (symbol_name) - strlen ("_get_type")),
+ "_", "");
+
+ switch (type_fundamental)
+ {
+ case G_TYPE_OBJECT:
+ g_igenerator_create_object (igenerator, symbol_name, type_id,
+ lower_case_prefix);
+ break;
+ case G_TYPE_INTERFACE:
+ g_igenerator_create_interface (igenerator, symbol_name, type_id,
+ lower_case_prefix);
+ break;
+ case G_TYPE_BOXED:
+ g_igenerator_create_boxed (igenerator, symbol_name, type_id,
+ lower_case_prefix);
+ break;
+ case G_TYPE_ENUM:
+ g_igenerator_create_enum (igenerator, symbol_name, type_id,
+ lower_case_prefix);
+ break;
+ case G_TYPE_FLAGS:
+ g_igenerator_create_flags (igenerator, symbol_name, type_id,
+ lower_case_prefix);
+ break;
+ default:
+ break;
+ }
+ return TRUE;
+}
+
+static void
+g_igenerator_process_module (GIGenerator * igenerator,
+ const gchar *filename)
+{
+ GModule *module;
+ GList *l;
+
+ module = g_module_open (filename,
+ G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+
+ if (module == NULL)
+ {
+ g_critical ("Couldn't open module: %s", filename);
+ return;
+ }
+
+ for (l = igenerator->get_type_symbols; l != NULL; l = l->next)
+ {
+ if (g_igenerator_process_module_symbol (igenerator,
+ module, (const char *)l->data))
+ /* symbol found, ignore in future iterations */
+ l->data = NULL;
+ }
+}
+
+static GIdlNodeType *
+get_type_from_ctype (CType * ctype)
+{
+ GIdlNodeType *gitype = (GIdlNodeType *) g_idl_node_new (G_IDL_NODE_TYPE);
+ if (ctype->type == CTYPE_VOID)
+ {
+ gitype->unparsed = g_strdup ("void");
+ }
+ else if (ctype->type == CTYPE_BASIC_TYPE)
+ {
+ gitype->unparsed = g_strdup (ctype->name);
+ }
+ else if (ctype->type == CTYPE_TYPEDEF)
+ {
+ gitype->unparsed = g_strdup (ctype->name);
+ }
+ else if (ctype->type == CTYPE_STRUCT)
+ {
+ if (ctype->name == NULL)
+ {
+ /* anonymous struct */
+ gitype->unparsed = g_strdup ("gpointer");
+ }
+ else
+ {
+ gitype->unparsed = g_strdup_printf ("struct %s", ctype->name);
+ }
+ }
+ else if (ctype->type == CTYPE_UNION)
+ {
+ if (ctype->name == NULL)
+ {
+ /* anonymous union */
+ gitype->unparsed = g_strdup ("gpointer");
+ }
+ else
+ {
+ gitype->unparsed = g_strdup_printf ("union %s", ctype->name);
+ }
+ }
+ else if (ctype->type == CTYPE_ENUM)
+ {
+ if (ctype->name == NULL)
+ {
+ /* anonymous enum */
+ gitype->unparsed = g_strdup ("gint");
+ }
+ else
+ {
+ gitype->unparsed = g_strdup_printf ("enum %s", ctype->name);
+ }
+ }
+ else if (ctype->type == CTYPE_POINTER)
+ {
+ if (ctype->base_type->type == CTYPE_FUNCTION)
+ {
+ /* anonymous function pointer */
+ gitype->unparsed = g_strdup ("GCallback");
+ }
+ else
+ {
+ GIdlNodeType *gibasetype = get_type_from_ctype (ctype->base_type);
+ gitype->unparsed = g_strdup_printf ("%s*", gibasetype->unparsed);
+ }
+ }
+ else if (ctype->type == CTYPE_ARRAY)
+ {
+ GIdlNodeType *gibasetype = get_type_from_ctype (ctype->base_type);
+ gitype->unparsed = g_strdup_printf ("%s[]", gibasetype->unparsed);
+ }
+ else
+ {
+ gitype->unparsed = g_strdup ("unknown");
+ }
+ return gitype;
+}
+
+static void
+g_igenerator_process_function_symbol (GIGenerator * igenerator, CSymbol * sym)
+{
+ GIdlNodeFunction *gifunc =
+ (GIdlNodeFunction *) g_idl_node_new (G_IDL_NODE_FUNCTION);
+ /* check whether this is a type method */
+ char *last_underscore = strrchr (sym->ident, '_');
+ GList *param_l;
+ int i;
+ GSList *l;
+
+ while (last_underscore != NULL)
+ {
+ char *prefix =
+ str_replace (g_strndup (sym->ident, last_underscore - sym->ident),
+ "_", "");
+ GIdlNode *ginode =
+ g_hash_table_lookup (igenerator->type_by_lower_case_prefix, prefix);
+ if (ginode != NULL)
+ {
+ gifunc->node.name = g_strdup (last_underscore + 1);
+ if (strcmp (gifunc->node.name, "get_type") == 0)
+ {
+ /* ignore get_type functions in registered types */
+ return;
+ }
+ if ((ginode->type == G_IDL_NODE_OBJECT
+ || ginode->type == G_IDL_NODE_BOXED)
+ && g_str_has_prefix (gifunc->node.name, "new"))
+ {
+ gifunc->is_constructor = TRUE;
+ }
+ else
+ {
+ gifunc->is_method = TRUE;
+ }
+ if (ginode->type == G_IDL_NODE_OBJECT
+ || ginode->type == G_IDL_NODE_INTERFACE)
+ {
+ GIdlNodeInterface *giiface = (GIdlNodeInterface *) ginode;
+ giiface->members =
+ g_list_insert_sorted (giiface->members, gifunc,
+ (GCompareFunc) g_idl_node_cmp);
+ break;
+ }
+ else if (ginode->type == G_IDL_NODE_BOXED)
+ {
+ GIdlNodeBoxed *giboxed = (GIdlNodeBoxed *) ginode;
+ giboxed->members =
+ g_list_insert_sorted (giboxed->members, gifunc,
+ (GCompareFunc) g_idl_node_cmp);
+ break;
+ }
+ else if (ginode->type == G_IDL_NODE_STRUCT)
+ {
+ GIdlNodeStruct *gistruct = (GIdlNodeStruct *) ginode;
+ gistruct->members =
+ g_list_insert_sorted (gistruct->members, gifunc,
+ (GCompareFunc) g_idl_node_cmp);
+ break;
+ }
+ else if (ginode->type == G_IDL_NODE_UNION)
+ {
+ GIdlNodeUnion *giunion = (GIdlNodeUnion *) ginode;
+ giunion->members =
+ g_list_insert_sorted (giunion->members, gifunc,
+ (GCompareFunc) g_idl_node_cmp);
+ break;
+ }
+ }
+ else if (strcmp (igenerator->lower_case_namespace, prefix) == 0)
+ {
+ gifunc->node.name = g_strdup (last_underscore + 1);
+ gifunc->is_constructor = FALSE;
+ gifunc->is_method = FALSE;
+ igenerator->module->entries =
+ g_list_insert_sorted (igenerator->module->entries, gifunc,
+ (GCompareFunc) g_idl_node_cmp);
+ break;
+ }
+ last_underscore =
+ g_utf8_strrchr (sym->ident, last_underscore - sym->ident, '_');
+ }
+
+ /* create a namespace function if no prefix matches */
+ if (gifunc->node.name == NULL)
+ {
+ gifunc->node.name = sym->ident;
+ gifunc->is_constructor = FALSE;
+ gifunc->is_method = FALSE;
+ igenerator->module->entries =
+ g_list_insert_sorted (igenerator->module->entries, gifunc,
+ (GCompareFunc) g_idl_node_cmp);
+ }
+
+ gifunc->symbol = sym->ident;
+ gifunc->result = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+ gifunc->result->type = get_type_from_ctype (sym->base_type->base_type);
+
+ for (param_l = sym->base_type->child_list, i = 1; param_l != NULL;
+ param_l = param_l->next, i++)
+ {
+ CSymbol *param_sym = param_l->data;
+ GIdlNodeParam *param =
+ (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+ if (param_sym->ident == NULL)
+ {
+ param->node.name = g_strdup_printf ("p%d", i);
+ }
+ else
+ {
+ param->node.name = param_sym->ident;
+ }
+ param->type = get_type_from_ctype (param_sym->base_type);
+ gifunc->parameters = g_list_append (gifunc->parameters, param);
+ }
+
+ for (l = sym->directives; l; l = l->next)
+ {
+ CDirective *directive = (CDirective*)l->data;
+
+ if (!strcmp (directive->name, "deprecated"))
+ gifunc->deprecated = strcmp (directive->value, "1") == 0;
+ else
+ g_printerr ("Unknown function directive: %s\n",
+ directive->name);
+ }
+}
+
+static void
+g_igenerator_process_unregistered_struct_typedef (GIGenerator * igenerator,
+ CSymbol * sym,
+ CType * struct_type)
+{
+ GIdlNodeStruct *ginode =
+ (GIdlNodeStruct *) g_idl_node_new (G_IDL_NODE_STRUCT);
+ GList *member_l;
+ char *lower_case_prefix;
+
+ ginode->node.name = sym->ident;
+ igenerator->module->entries =
+ g_list_insert_sorted (igenerator->module->entries, ginode,
+ (GCompareFunc) g_idl_node_cmp);
+ lower_case_prefix = g_ascii_strdown (sym->ident, -1);
+ g_hash_table_insert (igenerator->type_map, sym->ident, ginode);
+ g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+ lower_case_prefix, ginode);
+
+ for (member_l = struct_type->child_list; member_l != NULL;
+ member_l = member_l->next)
+ {
+ CSymbol *member = member_l->data;
+ GIdlNodeField *gifield =
+ (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
+
+ ginode->members = g_list_append (ginode->members, gifield);
+ gifield->node.name = member->ident;
+ gifield->type = get_type_from_ctype (member->base_type);
+ }
+}
+
+static void
+g_igenerator_process_struct_typedef (GIGenerator * igenerator, CSymbol * sym)
+{
+ CType *struct_type = sym->base_type;
+ gboolean opaque_type = FALSE;
+ GIdlNode *gitype;
+
+ if (struct_type->child_list == NULL)
+ {
+ CSymbol *struct_symbol;
+ g_assert (struct_type->name != NULL);
+ struct_symbol =
+ g_hash_table_lookup (igenerator->struct_or_union_or_enum_table,
+ struct_type->name);
+ if (struct_symbol != NULL)
+ {
+ struct_type = struct_symbol->base_type;
+ }
+ }
+
+ if (struct_type->child_list == NULL)
+ {
+ opaque_type = TRUE;
+ }
+
+ gitype = g_hash_table_lookup (igenerator->type_map, sym->ident);
+ if (gitype != NULL)
+ {
+ /* struct of a GTypeInstance */
+ if (!opaque_type
+ && (gitype->type == G_IDL_NODE_OBJECT
+ || gitype->type == G_IDL_NODE_INTERFACE))
+ {
+ GIdlNodeInterface *ginode = (GIdlNodeInterface *) gitype;
+ GList *member_l;
+ /* ignore first field => parent */
+ for (member_l = struct_type->child_list->next; member_l != NULL;
+ member_l = member_l->next)
+ {
+ CSymbol *member = member_l->data;
+ /* ignore private / reserved members */
+ if (member->ident[0] == '_'
+ || g_str_has_prefix (member->ident, "priv"))
+ {
+ continue;
+ }
+ GIdlNodeField *gifield =
+ (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
+ ginode->members = g_list_append (ginode->members, gifield);
+ gifield->node.name = member->ident;
+ gifield->type = get_type_from_ctype (member->base_type);
+ }
+ }
+ else if (gitype->type == G_IDL_NODE_BOXED)
+ {
+ GIdlNodeBoxed *ginode = (GIdlNodeBoxed *) gitype;
+ GList *member_l;
+ for (member_l = struct_type->child_list; member_l != NULL;
+ member_l = member_l->next)
+ {
+ CSymbol *member = member_l->data;
+ GIdlNodeField *gifield =
+ (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
+ ginode->members = g_list_append (ginode->members, gifield);
+ gifield->node.name = member->ident;
+ gifield->type = get_type_from_ctype (member->base_type);
+ }
+ }
+ }
+ else if (!opaque_type
+ && (g_str_has_suffix (sym->ident, "Class")
+ || g_str_has_suffix (sym->ident, "Iface")
+ || g_str_has_suffix (sym->ident, "Interface")))
+ {
+ char *base_name;
+ GList *member_l;
+ GIdlNodeInterface *ginode;
+
+ if (g_str_has_suffix (sym->ident, "Interface"))
+ {
+ base_name =
+ g_strndup (sym->ident,
+ strlen (sym->ident) - strlen ("Interface"));
+ }
+ else
+ {
+ base_name =
+ g_strndup (sym->ident, strlen (sym->ident) - strlen ("Class"));
+ }
+ gitype = g_hash_table_lookup (igenerator->type_map, base_name);
+ if (gitype == NULL
+ || (gitype->type != G_IDL_NODE_OBJECT
+ && gitype->type != G_IDL_NODE_INTERFACE))
+ {
+ g_igenerator_process_unregistered_struct_typedef (igenerator, sym,
+ struct_type);
+ return;
+ }
+ ginode = (GIdlNodeInterface *) gitype;
+
+ /* ignore first field => parent */
+ for (member_l = struct_type->child_list->next; member_l != NULL;
+ member_l = member_l->next)
+ {
+ CSymbol *member = member_l->data;
+ /* ignore private / reserved members */
+ if (member->ident[0] == '_')
+ {
+ continue;
+ }
+ if (member->base_type->type == CTYPE_POINTER
+ && member->base_type->base_type->type == CTYPE_FUNCTION)
+ {
+ /* ignore default handlers of signals */
+ gboolean found_signal = FALSE;
+ GList *type_member_l;
+ GList *param_l;
+ int i;
+ GIdlNodeVFunc *givfunc;
+
+ for (type_member_l = ginode->members; type_member_l != NULL;
+ type_member_l = type_member_l->next)
+ {
+ GIdlNode *type_member = type_member_l->data;
+ char *normalized_name =
+ str_replace (type_member->name, "-", "_");
+ if (type_member->type == G_IDL_NODE_SIGNAL
+ && strcmp (normalized_name, member->ident) == 0)
+ {
+ GList *vfunc_param_l;
+ GList *sig_param_l;
+ GIdlNodeSignal *sig = (GIdlNodeSignal *) type_member;
+ found_signal = TRUE;
+ /* set signal parameter names */
+ for (vfunc_param_l =
+ member->base_type->base_type->child_list,
+ sig_param_l = sig->parameters;
+ vfunc_param_l != NULL && sig_param_l != NULL;
+ vfunc_param_l = vfunc_param_l->next, sig_param_l =
+ sig_param_l->next)
+ {
+ CSymbol *vfunc_param = vfunc_param_l->data;
+ GIdlNodeParam *sig_param = sig_param_l->data;
+ if (vfunc_param->ident != NULL)
+ {
+ g_free (sig_param->node.name);
+ sig_param->node.name =
+ g_strdup (vfunc_param->ident);
+ }
+ }
+ break;
+ }
+ }
+ if (found_signal)
+ {
+ continue;
+ }
+
+ givfunc = (GIdlNodeVFunc *) g_idl_node_new (G_IDL_NODE_VFUNC);
+ givfunc->node.name = member->ident;
+ ginode->members =
+ g_list_insert_sorted (ginode->members, givfunc,
+ (GCompareFunc) g_idl_node_cmp);
+ givfunc->result =
+ (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+ givfunc->result->type =
+ get_type_from_ctype (member->base_type->base_type->base_type);
+ for (param_l = member->base_type->base_type->child_list, i = 1;
+ param_l != NULL; param_l = param_l->next, i++)
+ {
+ CSymbol *param_sym = param_l->data;
+ GIdlNodeParam *param =
+ (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+ if (param_sym->ident == NULL)
+ {
+ param->node.name = g_strdup_printf ("p%d", i);
+ }
+ else
+ {
+ param->node.name = param_sym->ident;
+ }
+ param->type = get_type_from_ctype (param_sym->base_type);
+ givfunc->parameters =
+ g_list_append (givfunc->parameters, param);
+ }
+ }
+ }
+ }
+ else if (g_str_has_suffix (sym->ident, "Private"))
+ {
+ /* ignore private structs */
+ }
+ else
+ {
+ g_igenerator_process_unregistered_struct_typedef (igenerator, sym,
+ struct_type);
+ }
+}
+
+static void
+g_igenerator_process_union_typedef (GIGenerator * igenerator, CSymbol * sym)
+{
+ CType *union_type = sym->base_type;
+ gboolean opaque_type = FALSE;
+ GIdlNode *gitype;
+
+ if (union_type->child_list == NULL)
+ {
+ g_assert (union_type->name != NULL);
+ CSymbol *union_symbol =
+ g_hash_table_lookup (igenerator->struct_or_union_or_enum_table,
+ union_type->name);
+ if (union_symbol != NULL)
+ {
+ union_type = union_symbol->base_type;
+ }
+ }
+ if (union_type->child_list == NULL)
+ {
+ opaque_type = TRUE;
+ }
+
+ gitype = g_hash_table_lookup (igenerator->type_map, sym->ident);
+ if (gitype != NULL)
+ {
+ g_assert (gitype->type == G_IDL_NODE_BOXED);
+ GIdlNodeBoxed *ginode = (GIdlNodeBoxed *) gitype;
+ GList *member_l;
+ for (member_l = union_type->child_list; member_l != NULL;
+ member_l = member_l->next)
+ {
+ CSymbol *member = member_l->data;
+ GIdlNodeField *gifield =
+ (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
+ ginode->members = g_list_append (ginode->members, gifield);
+ gifield->node.name = member->ident;
+ gifield->type = get_type_from_ctype (member->base_type);
+ }
+ }
+ else
+ {
+ GIdlNodeUnion *ginode =
+ (GIdlNodeUnion *) g_idl_node_new (G_IDL_NODE_UNION);
+ char *lower_case_prefix;
+ GList *member_l;
+
+ ginode->node.name = sym->ident;
+ igenerator->module->entries =
+ g_list_insert_sorted (igenerator->module->entries, ginode,
+ (GCompareFunc) g_idl_node_cmp);
+ lower_case_prefix = g_ascii_strdown (sym->ident, -1);
+ g_hash_table_insert (igenerator->type_map, sym->ident, ginode);
+ g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+ lower_case_prefix, ginode);
+
+ ginode->node.name = sym->ident;
+ for (member_l = union_type->child_list; member_l != NULL;
+ member_l = member_l->next)
+ {
+ CSymbol *member = member_l->data;
+ GIdlNodeField *gifield =
+ (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
+ ginode->members = g_list_append (ginode->members, gifield);
+ gifield->node.name = member->ident;
+ gifield->type = get_type_from_ctype (member->base_type);
+ }
+ }
+}
+
+static void
+g_igenerator_process_enum_typedef (GIGenerator * igenerator, CSymbol * sym)
+{
+ CType *enum_type;
+ GList *member_l;
+ GIdlNodeEnum *ginode;
+ CSymbol *enum_symbol;
+
+ enum_type = sym->base_type;
+ if (enum_type->child_list == NULL)
+ {
+ g_assert (enum_type->name != NULL);
+ enum_symbol =
+ g_hash_table_lookup (igenerator->struct_or_union_or_enum_table,
+ enum_type->name);
+ if (enum_symbol != NULL)
+ {
+ enum_type = enum_symbol->base_type;
+ }
+ }
+ if (enum_type->child_list == NULL)
+ {
+ /* opaque type */
+ return;
+ }
+
+ ginode = g_hash_table_lookup (igenerator->type_map, sym->ident);
+ if (ginode != NULL)
+ {
+ return;
+ }
+
+ ginode = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_ENUM);
+ ginode->node.name = sym->ident;
+ igenerator->module->entries =
+ g_list_insert_sorted (igenerator->module->entries, ginode,
+ (GCompareFunc) g_idl_node_cmp);
+
+ for (member_l = enum_type->child_list; member_l != NULL;
+ member_l = member_l->next)
+ {
+ CSymbol *member = member_l->data;
+ GIdlNodeValue *gival =
+ (GIdlNodeValue *) g_idl_node_new (G_IDL_NODE_VALUE);
+ ginode->values = g_list_append (ginode->values, gival);
+ gival->node.name = member->ident;
+ gival->value = member->const_int;
+ }
+}
+
+static void
+g_igenerator_process_function_typedef (GIGenerator * igenerator,
+ CSymbol * sym)
+{
+ GList *param_l;
+ int i;
+
+ /* handle callback types */
+ GIdlNodeFunction *gifunc =
+ (GIdlNodeFunction *) g_idl_node_new (G_IDL_NODE_CALLBACK);
+
+ gifunc->node.name = sym->ident;
+ igenerator->module->entries =
+ g_list_insert_sorted (igenerator->module->entries, gifunc,
+ (GCompareFunc) g_idl_node_cmp);
+
+ gifunc->symbol = sym->ident;
+ gifunc->result = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+ gifunc->result->type =
+ get_type_from_ctype (sym->base_type->base_type->base_type);
+
+ for (param_l = sym->base_type->base_type->child_list, i = 1;
+ param_l != NULL; param_l = param_l->next, i++)
+ {
+ CSymbol *param_sym = param_l->data;
+ GIdlNodeParam *param =
+ (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+ if (param_sym->ident == NULL)
+ {
+ param->node.name = g_strdup_printf ("p%d", i);
+ }
+ else
+ {
+ param->node.name = param_sym->ident;
+ }
+ param->type = get_type_from_ctype (param_sym->base_type);
+ gifunc->parameters = g_list_append (gifunc->parameters, param);
+ }
+}
+
+static void
+g_igenerator_process_constant (GIGenerator * igenerator, CSymbol * sym)
+{
+ GIdlNodeConstant *giconst =
+ (GIdlNodeConstant *) g_idl_node_new (G_IDL_NODE_CONSTANT);
+ giconst->node.name = sym->ident;
+ igenerator->module->entries =
+ g_list_insert_sorted (igenerator->module->entries, giconst,
+ (GCompareFunc) g_idl_node_cmp);
+
+ giconst->type = (GIdlNodeType *) g_idl_node_new (G_IDL_NODE_TYPE);
+ if (sym->const_int_set)
+ {
+ giconst->type->unparsed = g_strdup ("int");
+ giconst->value = g_strdup_printf ("%d", sym->const_int);
+ }
+ else if (sym->const_string != NULL)
+ {
+ giconst->type->unparsed = g_strdup ("char*");
+ giconst->value = sym->const_string;
+ }
+}
+
+static void
+g_igenerator_process_symbols (GIGenerator * igenerator)
+{
+ GList *l;
+ /* process type symbols first to ensure complete type hashtables */
+ /* type symbols */
+ for (l = igenerator->symbol_list; l != NULL; l = l->next)
+ {
+ CSymbol *sym = l->data;
+ if (sym->ident[0] == '_')
+ {
+ /* ignore private / reserved symbols */
+ continue;
+ }
+ if (sym->type == CSYMBOL_TYPE_TYPEDEF)
+ {
+ if (sym->base_type->type == CTYPE_STRUCT)
+ {
+ g_igenerator_process_struct_typedef (igenerator, sym);
+ }
+ else if (sym->base_type->type == CTYPE_UNION)
+ {
+ g_igenerator_process_union_typedef (igenerator, sym);
+ }
+ else if (sym->base_type->type == CTYPE_ENUM)
+ {
+ g_igenerator_process_enum_typedef (igenerator, sym);
+ }
+ else if (sym->base_type->type == CTYPE_POINTER
+ && sym->base_type->base_type->type == CTYPE_FUNCTION)
+ {
+ g_igenerator_process_function_typedef (igenerator, sym);
+ }
+ else
+ {
+ GIdlNodeStruct *ginode =
+ (GIdlNodeStruct *) g_idl_node_new (G_IDL_NODE_STRUCT);
+ char *lower_case_prefix;
+
+ ginode->node.name = sym->ident;
+ igenerator->module->entries =
+ g_list_insert_sorted (igenerator->module->entries, ginode,
+ (GCompareFunc) g_idl_node_cmp);
+ lower_case_prefix = g_ascii_strdown (sym->ident, -1);
+ g_hash_table_insert (igenerator->type_map, sym->ident, ginode);
+ g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+ lower_case_prefix, ginode);
+ }
+ }
+ }
+ /* other symbols */
+ for (l = igenerator->symbol_list; l != NULL; l = l->next)
+ {
+ CSymbol *sym = l->data;
+ if (sym->ident[0] == '_')
+ {
+ /* ignore private / reserved symbols */
+ continue;
+ }
+ if (sym->type == CSYMBOL_TYPE_FUNCTION)
+ {
+ g_igenerator_process_function_symbol (igenerator, sym);
+ }
+ else if (sym->type == CSYMBOL_TYPE_CONST)
+ {
+ g_igenerator_process_constant (igenerator, sym);
+ }
+ }
+}
+
+void
+g_igenerator_add_symbol (GIGenerator * igenerator, CSymbol * symbol)
+{
+ /* only add symbols of main file */
+ gboolean found_filename = FALSE;
+ GList *l;
+ for (l = igenerator->filenames; l != NULL; l = l->next)
+ {
+ if (strcmp (l->data, igenerator->current_filename) == 0)
+ {
+ found_filename = TRUE;
+ break;
+ }
+ }
+
+ symbol->directives = g_slist_reverse (igenerator->directives);
+ igenerator->directives = NULL;
+
+ if (found_filename || igenerator->macro_scan)
+ {
+ igenerator->symbol_list =
+ g_list_prepend (igenerator->symbol_list, symbol);
+ }
+
+ if (symbol->type == CSYMBOL_TYPE_TYPEDEF)
+
+ {
+ g_hash_table_insert (igenerator->typedef_table, symbol->ident, symbol);
+ }
+ else if (symbol->type == CSYMBOL_TYPE_STRUCT
+ || symbol->type == CSYMBOL_TYPE_UNION
+ || symbol->type == CSYMBOL_TYPE_ENUM)
+ {
+ g_hash_table_insert (igenerator->struct_or_union_or_enum_table,
+ symbol->ident, symbol);
+ }
+}
+
+gboolean
+g_igenerator_is_typedef (GIGenerator * igenerator, const char *name)
+{
+ gboolean b = g_hash_table_lookup (igenerator->typedef_table, name) != NULL;
+ return b;
+}
+
+void
+g_igenerator_generate (GIGenerator * igenerator,
+ const gchar * filename,
+ GList *libraries)
+{
+ GList *l;
+
+ for (l = igenerator->symbol_list; l != NULL; l = l->next)
+ {
+ CSymbol *sym = l->data;
+ if (sym->type == CSYMBOL_TYPE_FUNCTION
+ && g_str_has_suffix (sym->ident, "_get_type"))
+ {
+ if (sym->base_type->child_list == NULL)
+ {
+ // ignore get_type functions with parameters
+ igenerator->get_type_symbols =
+ g_list_prepend (igenerator->get_type_symbols, sym->ident);
+ }
+ }
+ }
+
+ /* ensure to initialize GObject */
+ g_type_class_ref (G_TYPE_OBJECT);
+
+ for (l = libraries; l; l = l->next)
+ g_igenerator_process_module (igenerator, (const gchar*)l->data);
+
+ g_igenerator_process_symbols (igenerator);
+
+ g_idl_writer_save_file (igenerator->module, filename);
+}
+
+static int
+eat_hspace (FILE * f)
+{
+ int c;
+ do
+ {
+ c = fgetc (f);
+ }
+ while (c == ' ' || c == '\t');
+ return c;
+}
+
+static int
+eat_line (FILE * f, int c)
+{
+ while (c != EOF && c != '\n')
+ {
+ c = fgetc (f);
+ }
+ if (c == '\n')
+ {
+ c = fgetc (f);
+ if (c == ' ' || c == '\t')
+ {
+ c = eat_hspace (f);
+ }
+ }
+ return c;
+}
+
+static int
+read_identifier (FILE * f, int c, char **identifier)
+{
+ GString *id = g_string_new ("");
+ while (isalnum (c) || c == '_')
+ {
+ g_string_append_c (id, c);
+ c = fgetc (f);
+ }
+ *identifier = g_string_free (id, FALSE);
+ return c;
+}
+
+static void
+g_igenerator_parse_macros (GIGenerator * igenerator)
+{
+ GError *error = NULL;
+ char *tmp_name = NULL;
+ FILE *fmacros =
+ fdopen (g_file_open_tmp ("gen-introspect-XXXXXX.h", &tmp_name, &error),
+ "w+");
+ g_unlink (tmp_name);
+
+ GList *l;
+ for (l = igenerator->filenames; l != NULL; l = l->next)
+ {
+ FILE *f = fopen (l->data, "r");
+ int line = 1;
+
+ GString *define_line;
+ char *str;
+ gboolean error_line = FALSE;
+ int c = eat_hspace (f);
+ while (c != EOF)
+ {
+ if (c != '#')
+ {
+ /* ignore line */
+ c = eat_line (f, c);
+ line++;
+ continue;
+ }
+
+ /* print current location */
+ str = g_strescape (l->data, "");
+ fprintf (fmacros, "# %d \"%s\"\n", line, str);
+ g_free (str);
+
+ c = eat_hspace (f);
+ c = read_identifier (f, c, &str);
+ if (strcmp (str, "define") != 0 || (c != ' ' && c != '\t'))
+ {
+ g_free (str);
+ /* ignore line */
+ c = eat_line (f, c);
+ line++;
+ continue;
+ }
+ g_free (str);
+ c = eat_hspace (f);
+ c = read_identifier (f, c, &str);
+ if (strlen (str) == 0 || (c != ' ' && c != '\t' && c != '('))
+ {
+ g_free (str);
+ /* ignore line */
+ c = eat_line (f, c);
+ line++;
+ continue;
+ }
+ define_line = g_string_new ("#define ");
+ g_string_append (define_line, str);
+ g_free (str);
+ if (c == '(')
+ {
+ while (c != ')')
+ {
+ g_string_append_c (define_line, c);
+ c = fgetc (f);
+ if (c == EOF || c == '\n')
+ {
+ error_line = TRUE;
+ break;
+ }
+ }
+ if (error_line)
+ {
+ g_string_free (define_line, TRUE);
+ /* ignore line */
+ c = eat_line (f, c);
+ line++;
+ continue;
+ }
+
+ g_assert (c == ')');
+ g_string_append_c (define_line, c);
+ c = fgetc (f);
+
+ /* found function-like macro */
+ fprintf (fmacros, "%s\n", define_line->str);
+
+ g_string_free (define_line, TRUE);
+ /* ignore rest of line */
+ c = eat_line (f, c);
+ line++;
+ continue;
+ }
+ if (c != ' ' && c != '\t')
+ {
+ g_string_free (define_line, TRUE);
+ /* ignore line */
+ c = eat_line (f, c);
+ line++;
+ continue;
+ }
+ while (c != EOF && c != '\n')
+ {
+ g_string_append_c (define_line, c);
+ c = fgetc (f);
+ if (c == '\\')
+ {
+ c = fgetc (f);
+ if (c == '\n')
+ {
+ /* fold lines when seeing backslash new-line sequence */
+ c = fgetc (f);
+ }
+ else
+ {
+ g_string_append_c (define_line, '\\');
+ }
+ }
+ }
+
+ /* found object-like macro */
+ fprintf (fmacros, "%s\n", define_line->str);
+
+ c = eat_line (f, c);
+ line++;
+ }
+
+ fclose (f);
+ }
+
+ igenerator->macro_scan = TRUE;
+ rewind (fmacros);
+
+ g_igenerator_parse_file (igenerator, fmacros);
+ fclose (fmacros);
+
+ igenerator->macro_scan = FALSE;
+}
+
+static void
+g_igenerator_add_module (GIGenerator *igenerator,
+ GIdlModule *module)
+{
+ GList *l;
+
+ for (l = module->entries; l; l = l->next)
+ {
+ GIdlNode *node = (GIdlNode*)l->data;
+
+ if (node->type == G_IDL_NODE_OBJECT)
+ {
+ GIdlNodeInterface *object = (GIdlNodeInterface*)node;
+ gchar *name;
+ if (strcmp(module->name, igenerator->namespace) == 0)
+ name = g_strdup (node->name);
+ else
+ name = g_strdup_printf ("%s.%s", module->name, node->name);
+ g_hash_table_insert (igenerator->symbols,
+ g_strdup (object->gtype_name),
+ name);
+ }
+ }
+}
+
+static void
+g_igenerator_add_include_idl (GIGenerator *igenerator,
+ const gchar *filename)
+{
+ GList *l;
+ GList *modules;
+
+ GError *error = NULL;
+
+ modules = g_idl_parse_file (filename, &error);
+ if (error)
+ {
+ g_printerr ("An error occured while parsing %s: %s\n",
+ filename, error->message);
+ return;
+ }
+
+ for (l = modules; l; l = l->next)
+ {
+ GIdlModule *module = (GIdlModule*)l->data;
+ g_igenerator_add_module (igenerator, module);
+ }
+}
+
+static FILE *
+g_igenerator_start_preprocessor (GIGenerator *igenerator,
+ GList *cpp_options)
+{
+ int cpp_out = -1, cpp_in = -1;
+ int cpp_argc = 0;
+ char **cpp_argv;
+ GList *l;
+ GError *error = NULL;
+ FILE *f, *out;
+ GPid pid;
+ int status = 0;
+ int read_bytes;
+ int i;
+ char **buffer;
+ int tmp;
+ char *tmpname;
+
+ cpp_argv = g_new0 (char *, g_list_length (cpp_options) + 4);
+ cpp_argv[cpp_argc++] = "cpp";
+ cpp_argv[cpp_argc++] = "-C";
+
+ /* Disable GCC extensions as we cannot parse them yet */
+ cpp_argv[cpp_argc++] = "-U__GNUC__";
+
+ for (l = cpp_options; l; l = l->next)
+ cpp_argv[cpp_argc++] = (char*)l->data;
+
+ cpp_argv[cpp_argc++] = NULL;
+
+ if (igenerator->verbose)
+ {
+ GString *args = g_string_new ("");
+
+ for (i = 0; i < cpp_argc - 1; i++)
+ {
+ g_string_append (args, cpp_argv[i]);
+ if (i < cpp_argc - 2)
+ g_string_append_c (args, ' ');
+ }
+
+ g_printf ("Executing '%s'\n", args->str);
+ g_string_free (args, FALSE);
+ }
+ g_spawn_async_with_pipes (NULL, cpp_argv, NULL,
+ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL, NULL, &pid, &cpp_in, &cpp_out, NULL, &error);
+
+ g_free (cpp_argv);
+ if (error != NULL)
+ {
+ g_error ("%s", error->message);
+ return NULL;
+ }
+
+ f = fdopen (cpp_in, "w");
+
+ for (l = igenerator->filenames; l != NULL; l = l->next)
+ {
+ if (igenerator->verbose)
+ g_printf ("Pre-processing %s\n", (char*)l->data);
+
+ fprintf (f, "#include <%s>\n", (char *) l->data);
+
+ }
+
+ fclose (f);
+ close (cpp_in);
+
+ tmp = g_file_open_tmp (NULL, &tmpname, &error);
+ if (error != NULL)
+ {
+ g_error (error->message);
+ return NULL;
+ }
+
+ buffer = g_malloc0 (4096 * sizeof (char));
+
+ while (1)
+ {
+ read_bytes = read (cpp_out, buffer, 4096);
+ if (read_bytes == 0)
+ break;
+ write (tmp, buffer, read_bytes);
+ }
+
+ g_free (buffer);
+
+ close (cpp_out);
+
+ if (waitpid (pid, &status, 0) > 0)
+ {
+ if (status != 0)
+ {
+ g_spawn_close_pid (pid);
+ kill (pid, SIGKILL);
+
+ g_error ("cpp returned error code: %d\n", status);
+ unlink (tmpname);
+ g_free (tmpname);
+ return NULL;
+ }
+ }
+
+ f = fdopen (tmp, "r");
+ if (!f)
+ {
+ g_error (strerror (errno));
+ unlink (tmpname);
+ g_free (tmpname);
+ return NULL;
+ }
+ rewind (f);
+ unlink (tmpname);
+ g_free (tmpname);
+
+ return f;
+}
+
+
+void
+g_igenerator_set_verbose (GIGenerator *igenerator,
+ gboolean verbose)
+{
+ igenerator->verbose = verbose;
+}
+
+int
+main (int argc, char **argv)
+{
+ GOptionContext *ctx;
+ gchar *namespace = NULL;
+ gchar *shared_library = NULL;
+ gchar **include_idls = NULL;
+ gchar *output = NULL;
+ gboolean verbose = FALSE;
+
+ GIGenerator *igenerator;
+ int gopt_argc, i;
+ char **gopt_argv;
+ GList *filenames = NULL;
+ GError *error = NULL;
+ GList *l, *libraries = NULL;
+ GList *cpp_options = NULL;
+ char *buffer;
+ size_t size;
+ FILE *tmp;
+ GOptionEntry entries[] =
+ {
+ { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
+ "Be verbose" },
+ { "output", 'o', 0, G_OPTION_ARG_STRING, &output,
+ "write output here instead of stdout", "FILE" },
+ { "namespace", 'n', 0, G_OPTION_ARG_STRING, &namespace,
+ "Namespace of the module, like 'Gtk'", "NAMESPACE" },
+ { "shared-library", 0, 0, G_OPTION_ARG_FILENAME, &shared_library,
+ "Shared library which contains the symbols", "FILE" },
+ { "include-idl", 0, 0, G_OPTION_ARG_STRING_ARRAY, &include_idls,
+ "Other gidls to include", "IDL" },
+ { NULL }
+ };
+
+ gopt_argc = 1;
+ gopt_argv = (char**)g_malloc (argc * sizeof (char*));
+ gopt_argv[0] = argv[0];
+
+ for (i = 1; i < argc; i++)
+ {
+ if (argv[i][0] == '-')
+ {
+ switch (argv[i][1])
+ {
+ case 'I':
+ case 'D':
+ case 'U':
+ cpp_options = g_list_prepend (cpp_options, g_strdup (argv[i]));
+ break;
+ default:
+ gopt_argv[gopt_argc++] = argv[i];
+ break;
+ }
+ }
+ else if (g_str_has_suffix (argv[i], ".h"))
+ {
+ gchar* filename;
+
+ if (!g_path_is_absolute (argv[i]))
+ {
+ gchar *dir = g_get_current_dir ();
+ filename = g_strdup_printf ("%s/%s", dir,
+ argv[i]);
+ g_free (dir);
+ }
+ else
+ filename = g_strdup (argv[i]);
+
+ filenames = g_list_append (filenames, filename);
+ }
+ else if (g_str_has_suffix (argv[i], ".la") ||
+ g_str_has_suffix (argv[i], ".so") ||
+ g_str_has_suffix (argv[i], ".dll"))
+ {
+ libraries = g_list_prepend (libraries, g_strdup (argv[i]));
+ }
+ else
+ {
+ gopt_argv[gopt_argc++] = argv[i];
+ }
+ }
+
+ ctx = g_option_context_new ("");
+ g_option_context_add_main_entries (ctx, entries, NULL);
+
+ if (!g_option_context_parse (ctx, &gopt_argc, &gopt_argv, &error))
+ {
+ g_printerr ("Parsing error: %s\n", error->message);
+ g_option_context_free (ctx);
+ return 1;
+ }
+
+ g_free (gopt_argv);
+ g_option_context_free (ctx);
+
+ if (!namespace)
+ {
+ g_printerr ("ERROR: namespace must be specified\n");
+ return 1;
+ }
+
+ igenerator = g_igenerator_new (namespace, shared_library);
+
+ if (verbose)
+ g_igenerator_set_verbose (igenerator, TRUE);
+
+ if (!filenames)
+ {
+ g_printerr ("ERROR: Need at least one header file.\n");
+ g_igenerator_free (igenerator);
+ return 0;
+ }
+ igenerator->filenames = filenames;
+ cpp_options = g_list_reverse (cpp_options);
+ libraries = g_list_reverse (libraries);
+
+ g_type_init ();
+
+ /* initialize threading as this may be required by libraries that we'll use
+ * libsoup-2.2 is an example of that.
+ */
+ g_thread_init (NULL);
+
+ if (include_idls)
+ {
+ for (i = 0; i < g_strv_length (include_idls); i++)
+ g_igenerator_add_include_idl (igenerator, include_idls[i]);
+ }
+
+ tmp = g_igenerator_start_preprocessor (igenerator, cpp_options);
+ if (!tmp)
+ {
+ g_error ("ERROR in pre-processor.\n");
+ g_igenerator_free (igenerator);
+ return 1;
+ }
+
+ if (!g_igenerator_parse_file (igenerator, tmp))
+ {
+ fclose (tmp);
+ g_igenerator_free (igenerator);
+ return 1;
+ }
+
+ g_igenerator_parse_macros (igenerator);
+
+ g_igenerator_generate (igenerator, output, libraries);
+
+ fclose (tmp);
+ g_igenerator_free (igenerator);
+
+ return 0;
+}
+
diff --git a/gobject-introspection/scanner.h b/gobject-introspection/scanner.h
new file mode 100644
index 000000000..b21407590
--- /dev/null
+++ b/gobject-introspection/scanner.h
@@ -0,0 +1,167 @@
+/* GObject introspection: gen-introspect
+ *
+ * Copyright (C) 2007 Jürg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.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 <j@bitron.ch>
+ */
+
+#ifndef __GEN_INTROSPECT_H__
+#define __GEN_INTROSPECT_H__
+
+#include <glib.h>
+#include "gidlmodule.h"
+
+G_BEGIN_DECLS typedef struct _GIGenerator GIGenerator;
+typedef struct _CSymbol CSymbol;
+typedef struct _CType CType;
+typedef struct _CDirective CDirective;
+
+struct _GIGenerator
+{
+ /* parameters */
+ char *namespace;
+ char *shared_library;
+ char *lower_case_namespace;
+ gboolean verbose;
+
+ /* specified files to be parsed */
+ GList *filenames;
+ /* source reference of current lexer position */
+ char *current_filename;
+ GList *symbol_list;
+ GHashTable *typedef_table;
+ GHashTable *struct_or_union_or_enum_table;
+
+ GIdlModule *module;
+ GList *get_type_symbols;
+ GHashTable *type_map;
+ GHashTable *type_by_lower_case_prefix;
+
+ GHashTable *symbols; /* typename -> module.name */
+
+ /* scanner variables */
+ gboolean macro_scan;
+ GSList *directives; /* list of CDirective for the current symbol */
+};
+
+typedef enum
+{
+ CSYMBOL_TYPE_INVALID,
+ CSYMBOL_TYPE_CONST,
+ CSYMBOL_TYPE_OBJECT,
+ CSYMBOL_TYPE_FUNCTION,
+ CSYMBOL_TYPE_STRUCT,
+ CSYMBOL_TYPE_UNION,
+ CSYMBOL_TYPE_ENUM,
+ CSYMBOL_TYPE_TYPEDEF
+} CSymbolType;
+
+struct _CSymbol
+{
+ CSymbolType type;
+ int id;
+ char *ident;
+ CType *base_type;
+ gboolean const_int_set;
+ int const_int;
+ char *const_string;
+ GSList *directives; /* list of CDirective */
+};
+
+typedef enum
+{
+ CTYPE_INVALID,
+ CTYPE_VOID,
+ CTYPE_BASIC_TYPE,
+ CTYPE_TYPEDEF,
+ CTYPE_STRUCT,
+ CTYPE_UNION,
+ CTYPE_ENUM,
+ CTYPE_POINTER,
+ CTYPE_ARRAY,
+ CTYPE_FUNCTION
+} CTypeType;
+
+typedef enum
+{
+ STORAGE_CLASS_NONE = 0,
+ STORAGE_CLASS_TYPEDEF = 1 << 1,
+ STORAGE_CLASS_EXTERN = 1 << 2,
+ STORAGE_CLASS_STATIC = 1 << 3,
+ STORAGE_CLASS_AUTO = 1 << 4,
+ STORAGE_CLASS_REGISTER = 1 << 5
+} StorageClassSpecifier;
+
+typedef enum
+{
+ TYPE_QUALIFIER_NONE = 0,
+ TYPE_QUALIFIER_CONST = 1 << 1,
+ TYPE_QUALIFIER_RESTRICT = 1 << 2,
+ TYPE_QUALIFIER_VOLATILE = 1 << 3
+} TypeQualifier;
+
+typedef enum
+{
+ FUNCTION_NONE = 0,
+ FUNCTION_INLINE = 1 << 1
+} FunctionSpecifier;
+
+typedef enum
+{
+ UNARY_ADDRESS_OF,
+ UNARY_POINTER_INDIRECTION,
+ UNARY_PLUS,
+ UNARY_MINUS,
+ UNARY_BITWISE_COMPLEMENT,
+ UNARY_LOGICAL_NEGATION
+} UnaryOperator;
+
+struct _CType
+{
+ CTypeType type;
+ StorageClassSpecifier storage_class_specifier;
+ TypeQualifier type_qualifier;
+ FunctionSpecifier function_specifier;
+ char *name;
+ CType *base_type;
+ GList *child_list;
+};
+
+struct _CDirective {
+ char *name;
+ char *value;
+};
+
+CSymbol * csymbol_new (CSymbolType type);
+gboolean csymbol_get_const_boolean (CSymbol *symbol);
+void csymbol_free (CSymbol *symbol);
+CDirective * cdirective_new (const gchar *name,
+ const gchar *value);
+void cdirective_free (CDirective *directive);
+
+gboolean g_igenerator_parse_file (GIGenerator *igenerator,
+ FILE *file);
+void g_igenerator_set_verbose (GIGenerator *igenerator,
+ gboolean verbose);
+void g_igenerator_add_symbol (GIGenerator *igenerator,
+ CSymbol *symbol);
+gboolean g_igenerator_is_typedef (GIGenerator *igenerator,
+ const char *name);
+G_END_DECLS
+#endif
diff --git a/gobject-introspection/clexer.l b/gobject-introspection/scannerlexer.l
index b0c9cd6cc..255f7dcd6 100644
--- a/gobject-introspection/clexer.l
+++ b/gobject-introspection/scannerlexer.l
@@ -1,3 +1,4 @@
+/* -*- Mode: C -*-
/* GObject introspection: C lexer
*
* Copyright (c) 1997 Sandro Sigala <ssigala@globalnet.it>
@@ -30,36 +31,38 @@
#include <ctype.h>
#include <stdio.h>
-#include "gen-introspect.h"
-#include "cparser.h"
+#include "scanner.h"
+#include "scannerparser.h"
int lineno;
+extern int yylex (GIGenerator *igenerator);
+#define YY_DECL int yylex (GIGenerator *igenerator)
static int yywrap (void);
-static void skip_comment (void);
-static void process_directive (void);
-static int check_identifier (const char *);
+static void parse_comment (GIGenerator *igenerator);
+static void process_directive (GIGenerator *igenerator);
+static int check_identifier (GIGenerator *igenerator, const char *);
%}
intsuffix ([uU][lL]?)|([lL][uU]?)
fracconst ([0-9]*\.[0-9]+)|([0-9]+\.)
exppart [eE][-+]?[0-9]+
floatsuffix [fFlL]
-chartext ([^'])|(\\.)
-stringtext ([^"])|(\\.)
+chartext ([^\'])|(\\.)
+stringtext ([^\"])|(\\.)
%%
-"\n" { ++lineno; }
+"\n" { ++lineno; } /* " */
[\t\f\v\r ]+ { /* Ignore whitespace. */ }
-"/*" { skip_comment(); }
+"/*" { parse_comment(igenerator); }
"//".* { }
"#define "[a-zA-Z_][a-zA-Z_0-9]*"(" { yyless (yyleng - 1); return FUNCTION_MACRO; }
"#define "[a-zA-Z_][a-zA-Z_0-9]* { return OBJECT_MACRO; }
-"#" { process_directive(); }
+"#" { process_directive(igenerator); }
"{" { return '{'; }
"<%" { return '{'; }
@@ -112,7 +115,7 @@ stringtext ([^"])|(\\.)
"," { return ','; }
"->" { return ARROW; }
-[a-zA-Z_][a-zA-Z_0-9]* { if (the_igenerator->macro_scan) return IDENTIFIER; else REJECT; }
+[a-zA-Z_][a-zA-Z_0-9]* { if (igenerator->macro_scan) return IDENTIFIER; else REJECT; }
"auto" { return AUTO; }
"break" { return BREAK; }
@@ -149,7 +152,7 @@ stringtext ([^"])|(\\.)
"volatile" { return VOLATILE; }
"while" { return WHILE; }
-[a-zA-Z_][a-zA-Z_0-9]* { return check_identifier(yytext); }
+[a-zA-Z_][a-zA-Z_0-9]* { return check_identifier(igenerator, yytext); }
"0"[xX][0-9a-fA-F]+{intsuffix}? { return INTEGER; }
"0"[0-7]+{intsuffix}? { return INTEGER; }
@@ -164,38 +167,95 @@ stringtext ([^"])|(\\.)
"\""{stringtext}*"\"" { return STRING; }
"L\""{stringtext}*"\"" { return STRING; }
-. { fprintf(stderr, "%s:%d: unexpected character `%c'\n", the_igenerator->current_filename, lineno, yytext[0]); }
+. { fprintf(stderr, "%s:%d: unexpected character `%c'\n", igenerator->current_filename, lineno, yytext[0]); }
%%
static int yywrap (void)
{
- return 1;
+ return 1;
}
-static void skip_comment (void)
+static void parse_gtkdoc (GIGenerator *igenerator, int *c1, int *c2)
{
- int c1, c2;
-
- c1 = input();
- c2 = input();
+ gboolean isline = FALSE;
+ gchar line[256];
+ int i;
+ gchar **parts;
+ CDirective *directive;
+ char *name, *value;
+
+ i = 0;
+ do {
+ *c1 = *c2;
+ if (*c1 == '\n')
+ {
+ isline = TRUE;
+ break;
+ }
+ if (i >= 256)
+ break;
+ line[i++] = *c1;
+ *c2 = input();
+
+ } while (*c2 != EOF && !(*c1 == '*' && *c2 == '/'));
+
+ if (!isline)
+ return;
+
+ line[i] = '\0';
+
+ parts = g_strsplit (line, ": ", 2);
+
+ if (g_strv_length (parts) == 2)
+ {
+ name = parts[0];
+ value = parts[1];
+ }
+ else /* parts == 1 */
+ {
+ name = parts[0];
+ value = "1";
+ }
+
+ directive = cdirective_new (name, value);
+ igenerator->directives = g_slist_prepend (igenerator->directives,
+ directive);
+
+ g_strfreev (parts);
+}
- while (c2 != EOF && !(c1 == '*' && c2 == '/')) {
- if (c1 == '\n')
- ++lineno;
- c1 = c2;
- c2 = input();
+static void parse_comment (GIGenerator *igenerator)
+{
+ int c1, c2;
+
+ c1 = input();
+ c2 = input();
+
+ while (c2 != EOF && !(c1 == '*' && c2 == '/'))
+ {
+ if (c1 == '\n')
+ ++lineno;
+ c1 = c2;
+ c2 = input();
+
+ if (c1 == ' ' && c2 == '@')
+ {
+ c1 = c2;
+ c2 = input();
+ parse_gtkdoc (igenerator, &c1, &c2);
}
+ }
}
-static int check_identifier (const char *s)
+static int check_identifier (GIGenerator *igenerator, const char *s)
{
/*
* This function checks if `s' is a type name or an
* identifier.
*/
- if (g_igenerator_is_typedef (the_igenerator, s)) {
+ if (g_igenerator_is_typedef (igenerator, s)) {
return TYPEDEF_NAME;
} else if (strcmp (s, "__builtin_va_list") == 0) {
return TYPEDEF_NAME;
@@ -204,7 +264,7 @@ static int check_identifier (const char *s)
return IDENTIFIER;
}
-static void process_directive (void)
+static void process_directive (GIGenerator *igenerator)
{
/* extract current filename from #line directives */
GString *filename_builder;
@@ -242,8 +302,8 @@ static void process_directive (void)
if (filename_builder->len > 0) {
char *filename = g_strcompress (filename_builder->str);
- g_free (the_igenerator->current_filename);
- the_igenerator->current_filename = filename;
+ g_free (igenerator->current_filename);
+ igenerator->current_filename = filename;
}
g_string_free (filename_builder, TRUE);
diff --git a/gobject-introspection/cparser.y b/gobject-introspection/scannerparser.y
index c29ca8f81..fae5067db 100644
--- a/gobject-introspection/cparser.y
+++ b/gobject-introspection/scannerparser.y
@@ -30,41 +30,177 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "gen-introspect.h"
+#include <errno.h>
+#include "scanner.h"
extern FILE *yyin;
extern int lineno;
extern char *yytext;
-extern int yylex (void);
-static void yyerror(const char *s);
-
+extern int yylex (GIGenerator *igenerator);
+static void yyerror(GIGenerator *igenerator, const char *s);
+
static int last_enum_value = -1;
static GHashTable *const_table = NULL;
+CSymbol *
+csymbol_new (CSymbolType type)
+{
+ CSymbol *s = g_new0 (CSymbol, 1);
+ s->type = type;
+ return s;
+}
+
+static void
+ctype_free (CType * type)
+{
+ g_free (type);
+ g_free (type->name);
+ g_list_foreach (type->child_list, (GFunc)ctype_free, NULL);
+ g_list_free (type->child_list);
+}
+
+void
+csymbol_free (CSymbol * symbol)
+{
+ g_free (symbol->ident);
+ ctype_free (symbol->base_type);
+ g_free (symbol->const_string);
+ g_free (symbol);
+ g_slist_foreach (symbol->directives, (GFunc)cdirective_free, NULL);
+ g_slist_free (symbol->directives);
+}
+
+gboolean
+csymbol_get_const_boolean (CSymbol * symbol)
+{
+ return (symbol->const_int_set && symbol->const_int) || symbol->const_string;
+}
+
+CType *
+ctype_new (CTypeType type)
+{
+ CType *t = g_new0 (CType, 1);
+ t->type = type;
+ return t;
+}
+
+CType *
+ctype_copy (CType * type)
+{
+ return g_memdup (type, sizeof (CType));
+}
+
+CType *
+cbasic_type_new (const char *name)
+{
+ CType *basic_type = ctype_new (CTYPE_BASIC_TYPE);
+ basic_type->name = g_strdup (name);
+ return basic_type;
+}
+
+CType *
+ctypedef_new (const char *name)
+{
+ CType *typedef_ = ctype_new (CTYPE_TYPEDEF);
+ typedef_->name = g_strdup (name);
+ return typedef_;
+}
+
+CType *
+cstruct_new (const char *name)
+{
+ CType *struct_ = ctype_new (CTYPE_STRUCT);
+ struct_->name = g_strdup (name);
+ return struct_;
+}
+
+CType *
+cunion_new (const char *name)
+{
+ CType *union_ = ctype_new (CTYPE_UNION);
+ union_->name = g_strdup (name);
+ return union_;
+}
+
+CType *
+cenum_new (const char *name)
+{
+ CType *enum_ = ctype_new (CTYPE_ENUM);
+ enum_->name = g_strdup (name);
+ return enum_;
+}
+
+CType *
+cpointer_new (CType * base_type)
+{
+ CType *pointer = ctype_new (CTYPE_POINTER);
+ pointer->base_type = ctype_copy (base_type);
+ return pointer;
+}
+
+CType *
+carray_new (void)
+{
+ CType *array = ctype_new (CTYPE_ARRAY);
+ return array;
+}
+
+CType *
+cfunction_new (void)
+{
+ CType *func = ctype_new (CTYPE_FUNCTION);
+ return func;
+}
+
/* use specified type as base type of symbol */
-static void csymbol_merge_type (CSymbol *symbol, CType *type)
+static void
+csymbol_merge_type (CSymbol *symbol, CType *type)
+{
+ CType **foundation_type = &(symbol->base_type);
+ while (*foundation_type != NULL) {
+ foundation_type = &((*foundation_type)->base_type);
+ }
+ *foundation_type = ctype_copy (type);
+}
+
+CDirective *
+cdirective_new (const gchar *name,
+ const gchar *value)
+{
+ CDirective *directive;
+
+ directive = g_slice_new (CDirective);
+ directive->name = g_strdup (name);
+ directive->value = g_strdup (value);
+ return directive;
+}
+
+void
+cdirective_free (CDirective *directive)
{
- CType **foundation_type = &(symbol->base_type);
- while (*foundation_type != NULL) {
- foundation_type = &((*foundation_type)->base_type);
- }
- *foundation_type = ctype_copy (type);
+ g_free (directive->name);
+ g_free (directive->value);
+ g_slice_free (CDirective, directive);
}
+
%}
%error-verbose
%union {
- char *str;
- GList *list;
- CSymbol *symbol;
- CType *ctype;
- StorageClassSpecifier storage_class_specifier;
- TypeQualifier type_qualifier;
- FunctionSpecifier function_specifier;
- UnaryOperator unary_operator;
+ char *str;
+ GList *list;
+ CSymbol *symbol;
+ CType *ctype;
+ StorageClassSpecifier storage_class_specifier;
+ TypeQualifier type_qualifier;
+ FunctionSpecifier function_specifier;
+ UnaryOperator unary_operator;
}
+%parse-param { GIGenerator* igenerator }
+%lex-param { GIGenerator* igenerator }
+
%token <str> IDENTIFIER "identifier"
%token <str> TYPEDEF_NAME "typedef-name"
@@ -530,7 +666,7 @@ declaration
} else {
sym->type = CSYMBOL_TYPE_OBJECT;
}
- g_igenerator_add_symbol (the_igenerator, sym);
+ g_igenerator_add_symbol (igenerator, sym);
}
}
| declaration_specifiers ';'
@@ -676,7 +812,7 @@ struct_or_union_specifier
}
sym->ident = g_strdup ($$->name);
sym->base_type = ctype_copy ($$);
- g_igenerator_add_symbol (the_igenerator, sym);
+ g_igenerator_add_symbol (igenerator, sym);
}
| struct_or_union '{' struct_declaration_list '}'
{
@@ -817,7 +953,7 @@ enumerator
$$->ident = $1;
$$->const_int_set = TRUE;
$$->const_int = ++last_enum_value;
- g_hash_table_insert (const_table, $$->ident, $$);
+ g_hash_table_insert (const_table, g_strdup ($$->ident), $$);
}
| identifier '=' constant_expression
{
@@ -826,7 +962,7 @@ enumerator
$$->const_int_set = TRUE;
$$->const_int = $3->const_int;
last_enum_value = $$->const_int;
- g_hash_table_insert (const_table, $$->ident, $$);
+ g_hash_table_insert (const_table, g_strdup ($$->ident), $$);
}
;
@@ -1192,7 +1328,7 @@ object_macro_define
{
if ($2->const_int_set || $2->const_string != NULL) {
$2->ident = $1;
- g_igenerator_add_symbol (the_igenerator, $2);
+ g_igenerator_add_symbol (igenerator, $2);
}
}
;
@@ -1206,31 +1342,35 @@ macro
%%
static void
-yyerror(const char *s)
+yyerror (GIGenerator *igenerator, const char *s)
{
- /* ignore errors while doing a macro scan as not all object macros
- * have valid expressions */
- if (!the_igenerator->macro_scan) {
- fprintf(stderr, "%s:%d: %s\n", the_igenerator->current_filename, lineno, s);
- }
+ /* ignore errors while doing a macro scan as not all object macros
+ * have valid expressions */
+ if (!igenerator->macro_scan)
+ {
+ fprintf(stderr, "%s:%d: %s\n",
+ igenerator->current_filename, lineno, s);
+ }
}
-void g_igenerator_parse (GIGenerator *igenerator, FILE *f)
+gboolean
+g_igenerator_parse_file (GIGenerator *igenerator, FILE *file)
{
- yyin = f;
- if (yyin == NULL) {
- return;
- }
-
- const_table = g_hash_table_new (g_str_hash, g_str_equal);
-
- lineno = 1;
- yyparse();
-
- g_hash_table_unref (const_table);
- const_table = NULL;
-
- fclose (yyin);
- yyin = NULL;
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ const_table = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ lineno = 1;
+ yyin = file;
+ yyparse (igenerator);
+
+ g_hash_table_destroy (const_table);
+ const_table = NULL;
+
+ yyin = NULL;
+
+ return TRUE;
}
+