gobject-introspection r130 - in trunk: girepository tools
- From: johan svn gnome org
- To: svn-commits-list gnome org
- Subject: gobject-introspection r130 - in trunk: girepository tools
- Date: Mon, 10 Mar 2008 17:46:00 +0000 (GMT)
Author: johan
Date: Mon Mar 10 17:45:59 2008
New Revision: 130
URL: http://svn.gnome.org/viewvc/gobject-introspection?rev=130&view=rev
Log:
2008-02-21 Mark Doffman <mark doffman codethink co uk>
* tools/gidlcompilercontext.c
* tools/gidlcompilercontext.h
* tools/gidlcompilerentrynode.c
* tools/gidlcompilerentrynode.h
* tools/gidlcompilertypenode.c
* tools/gidlcompilertypenode.h
Add code to compile a tree of GIdlNodes to
a 'C' struct representing the metadata.
This is to aid cross-compiling. Previously
the g-idl-compiler created a binary blob with
data written in the byte order and alignment
of the tool rather than the intended target.
Cleaned up and improved by Johan and Robert :-)
WARNING: This commit does not compile. It is a partial change.
Added:
trunk/tools/gidlcompilercontext.c
trunk/tools/gidlcompilercontext.h
trunk/tools/gidlcompilerentrynode.c
trunk/tools/gidlcompilerentrynode.h
trunk/tools/gidlcompilertypenode.c
trunk/tools/gidlcompilertypenode.h
Modified:
trunk/girepository/gmetadata.h
Modified: trunk/girepository/gmetadata.h
==============================================================================
--- trunk/girepository/gmetadata.h (original)
+++ trunk/girepository/gmetadata.h Mon Mar 10 17:45:59 2008
@@ -28,6 +28,7 @@
G_BEGIN_DECLS
#define G_IDL_MAGIC "GOBJ\nMETADATA\r\n\032"
+#define G_IDL_MAGIC_ESCAPED "GOBJ\\nMETADATA\\r\\n\\032"
enum
{
Added: trunk/tools/gidlcompilercontext.c
==============================================================================
--- (empty file)
+++ trunk/tools/gidlcompilercontext.c Mon Mar 10 17:45:59 2008
@@ -0,0 +1,663 @@
+/* GObject introspection: Metadata compiler context
+ *
+ * Copyright (C) 2008 Codethink Ltd
+ * 2008 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.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <glib.h>
+
+#include "gidlcompilercontext.h"
+#include "gidlnode.h"
+#include "gmetadata.h"
+
+/* STATIC FUNCTIONS */
+/* ---------------- */
+
+/* Functions for writing final 'C' file */
+/* ------------------------------------ */
+
+extern char gmetadata_header[];
+
+/* Parameters
+ * -Struct name
+ * -Number of directory entries
+ * -Length of strings area.
+ */
+static const char struct_header[] =
+ "%s\n"
+ "{\n"
+ " Header " SECTION (header) ";\n"
+ " DirEntry " SECTION (directory) "[%d];\n"
+ " char " SECTION (strings) "[%d];\n";
+
+/* Parameters
+ * -Namespace name
+ * -Struct name
+ */
+static const char declarations[] =
+ "const unsigned char *_G_METADATA = (unsigned char *) &_METADATA_%s;\n"
+ "const gsize _G_METADATA_SIZE = sizeof(%s);\n\n";
+
+/* Parameters
+ * -Struct name
+ * -Namespace name
+ */
+static const char init_header[] =
+ "static const %s _METADATA_%s =\n"
+ "{\n";
+
+/* Parameters
+ * -Namespace name
+ */
+static const char file_footer[] =
+ "__attribute__((constructor)) void\n"
+ "register_metadata (void)\n"
+ "{\n"
+ " GMetadata *metadata;\n"
+ " metadata = g_metadata_new_from_const_memory (_G_METADATA, _G_METADATA_SIZE);\n"
+ " g_irepository_register (NULL, metadata);\n"
+ "}\n"
+ "\n"
+ "__attribute__((destructor)) void\n"
+ "unregister_metadata (void)\n"
+ "{\n"
+ " g_irepository_unregister (NULL, \"%s\");\n"
+ "}\n";
+
+
+typedef struct
+{
+ guint entry_id;
+ guint dir_id;
+} SymbolEntry;
+
+typedef struct
+{
+ GIdlNode *node;
+ guint entry_id;
+} DeferredEntry;
+
+static void
+symbol_entry_free (SymbolEntry *symbol_entry)
+{
+ g_slice_free (SymbolEntry, symbol_entry);
+}
+
+static void
+deferred_entry_free (DeferredEntry *deferred_entry)
+{
+ g_slice_free (DeferredEntry, deferred_entry);
+}
+
+static void
+include_file (const gchar *fname,
+ FILE *output)
+{
+ FILE *input;
+ char c;
+
+ input = fopen (fname, "r");
+
+ c = fgetc (input);
+ while (c != EOF)
+ {
+ fputc (c, output);
+ c = fgetc (input);
+ }
+
+ fclose (input);
+}
+
+static void
+write_header (GIdlCompilerContext *ctx,
+ const gchar *shlib,
+ FILE *stream)
+{
+ guint32 n_entries;
+ guint32 n_local_entries;
+ const gchar *header_prototype =
+ " {\n"
+ /* Magic */
+ " \"%s\",\n"
+ /* Major version */
+ " %d,\n"
+ /* Minor version */
+ " %d,\n"
+ " 0,\n"
+ /* n_entries */
+ " %d,\n"
+ /* n_local_entries */
+ " %d,\n"
+ /* directory */
+ " G_STRUCT_OFFSET(%s, " SECTION (directory) "),\n"
+ /* n_annotations */
+ " %d,\n"
+ /* annotations */
+ " %d,\n"
+ /* struct_name */
+ " sizeof(%s),\n"
+ /* struct_name, pointer to name string */
+ " G_STRUCT_OFFSET(%s, " SECTION (strings) ") + %d,\n";
+
+ fprintf (stream, header_prototype,
+ G_IDL_MAGIC_ESCAPED,
+ 1,
+ 0,
+ ctx->directory_entries,
+ ctx->directory_local_entries,
+ ctx->struct_name,
+ 0,
+ 0,
+ ctx->struct_name,
+ ctx->struct_name,
+ g_idl_compiler_write_string (ctx, ctx->namespace_name));
+
+
+ /* Header */
+ if (shlib)
+ fprintf (stream, STRING_POINTER,
+ ctx->struct_name,
+ g_idl_compiler_write_string (ctx, shlib));
+ else
+ fprintf (stream, "0");
+ fprintf (stream, ",\n");
+
+ /* Header sizes */
+ fprintf (stream,
+ " sizeof(DirEntry),\n"
+ " sizeof(FunctionBlob),\n"
+ " sizeof(CallbackBlob),\n"
+ " sizeof(SignalBlob),\n"
+ " sizeof(VFuncBlob),\n"
+ " sizeof(ArgBlob),\n"
+ " sizeof(PropertyBlob),\n"
+ " sizeof(FieldBlob),\n"
+ " sizeof(ValueBlob),\n"
+ " sizeof(AnnotationBlob),\n"
+ " sizeof(ConstantBlob),\n"
+ " sizeof(ErrorDomainBlob),\n"
+ " sizeof(SignatureBlob),\n"
+ " sizeof(EnumBlob),\n"
+ " sizeof(StructBlob),\n"
+ " sizeof(ObjectBlob),\n"
+ " sizeof(InterfaceBlob),\n"
+ " sizeof(UnionBlob),\n"
+ " {0,0,0,0,0,0,0},\n" " },\n\n");
+}
+
+void
+write_compiled (GIdlCompilerContext *ctx, FILE *compiled,
+ const gchar *shlib,
+ GError **err)
+{
+ const char file_header[] =
+ "#include <stdlib.h>\n"
+ "#include <glib.h>\n"
+ "#include <girepository.h>\n";
+
+ /* Before doing anything need to add the namespace string */
+ g_idl_compiler_write_string (ctx, ctx->namespace_name);
+
+ fprintf (compiled, file_header);
+ fprintf (compiled, gmetadata_header);
+
+ /* +1 is for the null byte right at the end of the strings section */
+ fprintf (compiled, struct_header, ctx->struct_name,
+ ctx->directory_entries, ctx->string_offset + 1);
+
+ /* Include the struct file */
+ include_file (ctx->mdata_struct_fn, compiled);
+ fprintf (compiled, "};\n\n");
+ fprintf (compiled, init_header, ctx->struct_name, ctx->namespace_name);
+
+ write_header (ctx, shlib, compiled);
+
+ /* Close all the temporary files */
+ fclose (ctx->mdata_init);
+ fclose (ctx->mdata_string);
+ fclose (ctx->mdata_directory);
+
+ /* Place directory here */
+ fprintf (compiled, " {\n");
+ include_file (ctx->mdata_directory_fn, compiled);
+ fprintf (compiled, " },\n\n");
+
+ /* Place string data here */
+ fprintf (compiled, " {\n");
+ include_file (ctx->mdata_string_fn, compiled);
+ fprintf (compiled, " },\n\n");
+
+ /* Include the initializer file */
+ include_file (ctx->mdata_init_fn, compiled);
+
+ fprintf (compiled, "};\n\n");
+
+ /* Write out the metadata declarations */
+ fprintf (compiled, declarations, ctx->namespace_name, ctx->struct_name);
+
+ fprintf (compiled, file_footer, ctx->namespace_name);
+
+ /* Remove the temporary files */
+ g_remove (ctx->mdata_struct_fn);
+ g_remove (ctx->mdata_init_fn);
+ g_remove (ctx->mdata_string_fn);
+ g_remove (ctx->mdata_directory_fn);
+}
+
+/* GLOBAL FUNCTIONS */
+/* ---------------- */
+
+GIdlCompilerContext *
+g_idl_compiler_context_new (const gchar *namespace,
+ GError **error)
+{
+ gint struct_fd, init_fd, string_fd, directory_fd;
+ GIdlCompilerContext *ctx;
+ GError *tmp_error = NULL;
+
+ ctx = g_slice_new0 (GIdlCompilerContext);
+ if (!ctx)
+ {
+ /* FIXME Put proper error quark here */
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT,
+ "Could not create output context");
+ goto out;
+ }
+ ctx->strings = g_hash_table_new (g_str_hash, g_str_equal);
+ ctx->namespace_name = g_strdup (namespace);
+ ctx->struct_name = g_strdup_printf ("struct mdata_%s", namespace);
+
+ ctx->entriesdb = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)symbol_entry_free);
+ ctx->typesdb = g_hash_table_new (g_str_hash, g_str_equal);
+
+ /* Structure definition file */
+ struct_fd = g_file_open_tmp ("gicomp-XXXXXX", &ctx->mdata_struct_fn,
+ &tmp_error);
+ if (tmp_error)
+ goto error4;
+
+ /* Structure initialization file */
+ init_fd = g_file_open_tmp ("gicomp-XXXXXX", &ctx->mdata_init_fn,
+ &tmp_error);
+ if (tmp_error)
+ goto error3;
+
+ /* String file */
+ string_fd = g_file_open_tmp ("gicomp-XXXXXX", &ctx->mdata_string_fn,
+ &tmp_error);
+ if (tmp_error)
+ goto error2;
+
+ /* Directory file */
+ directory_fd = g_file_open_tmp ("gicomp-XXXXXX", &ctx->mdata_directory_fn,
+ &tmp_error);
+ if (tmp_error)
+ goto error1;
+
+ ctx->mdata_struct = fdopen (struct_fd, "w");
+ ctx->mdata_init = fdopen (init_fd, "w");
+ ctx->mdata_string = fdopen (string_fd, "w");
+ ctx->mdata_directory = fdopen (directory_fd, "w");
+
+ goto out;
+
+ error1:
+ close (directory_fd);
+ g_remove (ctx->mdata_directory_fn);
+ error2:
+ close (string_fd);
+ g_remove (ctx->mdata_string_fn);
+ error3:
+ close (init_fd);
+ g_remove (ctx->mdata_init_fn);
+ error4:
+ close (struct_fd);
+ g_remove (ctx->mdata_struct_fn);
+ error:
+ g_propagate_error (error, tmp_error);
+
+ g_free (ctx);
+ ctx = NULL;
+ out:
+ return ctx;
+}
+
+void
+g_idl_compiler_context_finalize (GIdlCompilerContext *ctx,
+ FILE *stream,
+ const gchar *shlib,
+ GError **error)
+{
+ fclose (ctx->mdata_struct);
+ write_compiled (ctx, stream, shlib, error);
+}
+
+void
+g_idl_compiler_context_destroy (GIdlCompilerContext *ctx)
+{
+ g_free (ctx->mdata_struct_fn);
+ g_free (ctx->mdata_init_fn);
+ g_free (ctx->mdata_string_fn);
+ g_free (ctx->mdata_directory_fn);
+
+ g_free (ctx->struct_name);
+ g_free (ctx->namespace_name);
+
+ g_list_foreach (ctx->dtypelist, (GFunc)deferred_entry_free, NULL);
+ g_list_free (ctx->dtypelist);
+
+ g_list_foreach (ctx->dconstantlist, (GFunc)deferred_entry_free, NULL);
+ g_list_free (ctx->dconstantlist);
+
+ g_hash_table_destroy (ctx->entriesdb);
+ g_hash_table_destroy (ctx->typesdb);
+ g_hash_table_destroy (ctx->strings);
+ g_slice_free (GIdlCompilerContext, ctx);
+}
+
+
+/**
+ * g_idl_compiler_write_string:
+ * @ctx:
+ * @str:
+ * String specific functions
+ *
+ * If string is already in the pool, return previous location,
+ * otherwise write string to the metadata at offset, put it
+ * in the pool and update offset.
+ */
+guint32
+g_idl_compiler_write_string (GIdlCompilerContext *ctx,
+ const gchar *str)
+{
+ gpointer value;
+ guint32 orig = ctx->string_offset;
+
+ g_return_val_if_fail (str != NULL, 0);
+
+ if (g_hash_table_lookup_extended (ctx->strings, str, NULL, &value))
+ return GPOINTER_TO_INT (value);
+
+ g_hash_table_insert (ctx->strings, (gpointer) str,
+ GINT_TO_POINTER (ctx->string_offset));
+
+ /* +1 is for the null byte that is added at the end of each string */
+ ctx->string_offset += strlen (str) + 1;
+
+ fprintf (ctx->mdata_string, " \"%s\\0\"\n", str);
+
+ return orig;
+}
+
+static guint16
+g_idl_compiler_write_dir_entry (GIdlCompilerContext *ctx,
+ guint16 blob_type,
+ const gchar *name,
+ gint entry_id)
+{
+ const char *entry_prototype =
+ " {\n" " %d,\n"
+ " %d,\n"
+ " 0,\n"
+ " " STRING_POINTER ",\n"
+ " " TYPE_POINTER ",\n"
+ " },\n";
+ guint orig = ctx->directory_entries;
+
+ fprintf (ctx->mdata_directory, entry_prototype,
+ blob_type,
+ TRUE,
+ ctx->struct_name, g_idl_compiler_write_string (ctx, name),
+ ctx->struct_name, entry_id);
+
+ ctx->directory_local_entries += 1;
+ ctx->directory_entries += 1;
+ return orig;
+}
+
+static guint16
+g_idl_compiler_write_xref_entry (GIdlCompilerContext *ctx,
+ guint16 blob_type,
+ const gchar *name,
+ const gchar *namespace)
+{
+ const char *entry_prototype =
+ " {\n" " %d,\n"
+ " %d,\n"
+ " 0,\n"
+ " " STRING_POINTER ",\n"
+ " " STRING_POINTER ",\n"
+ " },\n";
+ guint dir_id_res = ctx->directory_entries;
+
+ fprintf (ctx->mdata_directory, entry_prototype,
+ blob_type,
+ FALSE,
+ ctx->struct_name, g_idl_compiler_write_string (ctx, name),
+ ctx->struct_name, g_idl_compiler_write_string (ctx, namespace));
+
+ ctx->directory_entries += 1;
+ return dir_id_res;
+}
+
+/* This is a unique id for each entry in the
+ * metadata that may need to be referenced elsewhere.
+ * Essentially anything that has to be given a
+ * name in the metadata struct.
+ */
+gint32
+g_idl_compiler_get_unique_id (void)
+{
+ static gint32 i = 0;
+ return ++i;
+}
+
+void
+g_idl_compiler_add_entry (GIdlCompilerContext *ctx, GIdlNode *node)
+{
+ guint entry_id;
+ guint dir_id;
+ SymbolEntry *entry;
+
+ entry = g_slice_new0 (SymbolEntry);
+ entry_id = g_idl_compiler_get_unique_id ();
+ dir_id = g_idl_compiler_write_dir_entry (ctx, node->type,
+ node->name, entry_id);
+
+ entry->entry_id = entry_id;
+ /* The directory array is indexed from 1 upwards. Just to confuse us */
+ entry->dir_id = dir_id + 1;
+
+ g_hash_table_insert (ctx->entriesdb, g_strdup (node->name), entry);
+}
+
+static guint
+g_idl_compiler_add_xref (GIdlCompilerContext *ctx,
+ const gchar *name)
+{
+ gint dir_id;
+ guint n_names;
+ gchar **names;
+ gchar *symbol;
+ gchar *namespace;
+ SymbolEntry *entry;
+
+ names = g_strsplit (name, ".", 0);
+ n_names = g_strv_length (names);
+
+ if (n_names < 2)
+ {
+ g_warning ("External reference with no namespace");
+ symbol = g_strjoinv ("", &names[0]);
+ namespace = NULL;
+ }
+ else
+ {
+ symbol = g_strjoinv (".", &names[1]);
+ namespace = names[0];
+ }
+
+ fprintf (ctx->mdata_directory,
+ " {\n"
+ " 0,\n"
+ " 0,\n"
+ " 0,\n"
+ " " STRING_POINTER ",\n",
+ ctx->struct_name,
+ g_idl_compiler_write_string (ctx, symbol));
+
+ if (namespace)
+ fprintf (ctx->mdata_directory, " " STRING_POINTER ",\n",
+ ctx->struct_name, g_idl_compiler_write_string (ctx, namespace));
+ else
+ fprintf (ctx->mdata_directory, " 0,\n");
+ fprintf (ctx->mdata_directory, " },\n");
+
+ dir_id = ctx->directory_entries;
+ ctx->directory_entries += 1;
+
+ /* The Directory array is indexed from 1 upwards. Just to confuse us */
+ entry = g_slice_new0 (SymbolEntry);
+ entry->dir_id = dir_id + 1;
+ g_hash_table_insert (ctx->entriesdb, g_strdup (name), entry);
+
+ g_free(symbol);
+ g_strfreev (names);
+ return dir_id + 1;
+}
+
+guint
+g_idl_compiler_get_entry_id (GIdlCompilerContext *ctx,
+ const gchar *name)
+{
+ SymbolEntry *entry;
+
+ entry = g_hash_table_lookup (ctx->entriesdb, name);
+ return entry->entry_id;
+}
+
+guint
+g_idl_compiler_get_entry_dirid (GIdlCompilerContext *ctx,
+ const gchar *name)
+{
+ SymbolEntry *entry;
+
+ entry = g_hash_table_lookup (ctx->entriesdb, name);
+ if (entry)
+ return entry->dir_id;
+
+ /* If no entry found assume its an external reference */
+ return g_idl_compiler_add_xref (ctx, name);
+}
+
+void
+g_idl_compiler_push_deferred_type_node (GIdlCompilerContext *ctx,
+ GIdlNode *node,
+ guint entry_id)
+{
+ DeferredEntry *entry;
+
+ entry = g_slice_new (DeferredEntry);
+ entry->node = node;
+ entry->entry_id = entry_id;
+ ctx->dtypelist = g_list_prepend (ctx->dtypelist, entry);
+}
+
+GIdlNode *
+g_idl_compiler_pop_deferred_type_node (GIdlCompilerContext *ctx,
+ guint *entry_id)
+{
+ DeferredEntry *entry;
+ GIdlNode *node;
+
+ if (!ctx->dtypelist)
+ return NULL;
+
+ entry = (DeferredEntry *) ctx->dtypelist->data;
+ ctx->dtypelist = g_list_remove (ctx->dtypelist, (gpointer) entry);
+ *entry_id = entry->entry_id;
+ node = entry->node;
+ deferred_entry_free (entry);
+ return node;
+}
+
+void
+g_idl_compiler_push_deferred_signature_node (GIdlCompilerContext * ctx,
+ GIdlNode * node, guint entry_id)
+{
+ DeferredEntry *entry;
+
+ entry = g_slice_new (DeferredEntry);
+ entry->node = node;
+ entry->entry_id = entry_id;
+ ctx->dsignaturelist = g_list_prepend (ctx->dsignaturelist, entry);
+}
+
+GIdlNode*
+g_idl_compiler_pop_deferred_signature_node (GIdlCompilerContext *ctx,
+ guint *entry_id)
+{
+ DeferredEntry *entry;
+ GIdlNode *node;
+
+ if (!ctx->dsignaturelist)
+ return NULL;
+
+ entry = (DeferredEntry *) ctx->dsignaturelist->data;
+ ctx->dsignaturelist = g_list_remove (ctx->dsignaturelist, entry);
+ *entry_id = entry->entry_id;
+ node = entry->node;
+ deferred_entry_free (entry);
+ return node;
+}
+
+void
+g_idl_compiler_push_deferred_constant (GIdlCompilerContext *ctx,
+ GIdlNode *node,
+ guint entry_id)
+{
+ DeferredEntry *constant;
+
+ constant = g_slice_new (DeferredEntry);
+ constant->node = node;
+ constant->entry_id = entry_id;
+ ctx->dconstantlist = g_list_prepend (ctx->dconstantlist, constant);
+}
+
+GIdlNode *
+g_idl_compiler_pop_deferred_constant (GIdlCompilerContext *ctx,
+ guint *entry_id)
+{
+ DeferredEntry *deferred_entry;
+ GIdlNode *node;
+
+ if (!ctx->dconstantlist)
+ return NULL;
+
+ deferred_entry = (DeferredEntry *) ctx->dconstantlist->data;
+ ctx->dconstantlist = g_list_remove (ctx->dconstantlist, deferred_entry);
+ *entry_id = deferred_entry->entry_id;
+ node = deferred_entry->node;
+ deferred_entry_free (deferred_entry);
+ return node;
+}
Added: trunk/tools/gidlcompilercontext.h
==============================================================================
--- (empty file)
+++ trunk/tools/gidlcompilercontext.h Mon Mar 10 17:45:59 2008
@@ -0,0 +1,131 @@
+
+#ifndef __G_IDL_COMPILER_CONTEXT_H__
+#define __G_IDL_COMPILER_CONTEXT_H__
+
+#include <stdio.h>
+#include <glib.h>
+
+#include "gidlnode.h"
+
+typedef struct _GIdlCompilerContext GIdlCompilerContext;
+
+struct _GIdlCompilerContext
+{
+ gchar *namespace_name;
+ gchar *struct_name;
+
+ gchar *mdata_struct_fn;
+ FILE *mdata_struct;
+
+ gchar *mdata_init_fn;
+ FILE *mdata_init;
+
+ guint32 string_offset;
+ gchar *mdata_string_fn;
+ FILE *mdata_string;
+ GHashTable *strings;
+
+ guint32 directory_local_entries;
+ guint32 directory_entries;
+ gchar *mdata_directory_fn;
+ FILE *mdata_directory;
+
+ /* The entriesdb contains all the
+ * types that have a directory entry.
+ *
+ * It must be filled in before beginning to write
+ * out the data. This is because it is used
+ * to decide whether a type is available or
+ * needs an external reference
+ */
+ GHashTable *entriesdb;
+
+ /* The typesdb is used to store type names to
+ * entry ids, so that multiple similar type blobs are
+ * not written out
+ */
+ GHashTable *typesdb;
+
+ /* Type blobs are accessed in the middle of writing another
+ * entry. Writing them needs to be deferred until after
+ * that entry is finished.
+ */
+ GList *dtypelist;
+
+ /* Signature blobs are accessed in the middle of writing
+ * other entries, and so need to be deferred.
+ *
+ * There is no signature node, so the function / callback
+ * nodes are stored instead.
+ */
+ GList *dsignaturelist;
+
+ /* Constants have values that are of a variable size,
+ * and have to be written out after the entry has finished,
+ * so are stored as a variant in this list until the time comes.
+ */
+ GList *dconstantlist;
+};
+
+GIdlCompilerContext *g_idl_compiler_context_new (const gchar * namespace,
+ GError ** err);
+
+void
+g_idl_compiler_context_finalize (GIdlCompilerContext *ctx,
+ FILE *stream,
+ const gchar *shlib,
+ GError **err);
+
+void g_idl_compiler_context_destroy (GIdlCompilerContext * ctx);
+
+guint32 g_idl_compiler_write_string (GIdlCompilerContext * ctx,
+ const gchar * str);
+
+gint32 g_idl_compiler_get_unique_id (void);
+
+void g_idl_compiler_add_entry (GIdlCompilerContext *ctx,
+ GIdlNode *node);
+
+guint g_idl_compiler_get_entry_id (GIdlCompilerContext * ctx,
+ const gchar * name);
+
+guint g_idl_compiler_get_entry_dirid (GIdlCompilerContext * ctx,
+ const gchar * name);
+
+void g_idl_compiler_push_deferred_type_node (GIdlCompilerContext * ctx,
+ GIdlNode * node,
+ guint entry_id);
+
+GIdlNode *g_idl_compiler_pop_deferred_type_node (GIdlCompilerContext * ctx,
+ guint * entry_id);
+
+void g_idl_compiler_push_deferred_signature_node (GIdlCompilerContext * ctx,
+ GIdlNode * node,
+ guint entry_id);
+
+GIdlNode *g_idl_compiler_pop_deferred_signature_node (GIdlCompilerContext * ctx,
+ guint * entry_id);
+
+void g_idl_compiler_push_deferred_constant (GIdlCompilerContext * ctx,
+ GIdlNode * node,
+ guint entry_id);
+
+GIdlNode * g_idl_compiler_pop_deferred_constant (GIdlCompilerContext * ctx,
+ guint * entry_id);
+
+#define SECTION(sEC) "info_" #sEC
+#define ID_TO_ENTRY "entry_%d"
+
+/* Parameters (To the string)
+ * Metadata struct name
+ * Offset into string buffer - Given by g_idl_compiler_write_string()
+ */
+#define STRING_POINTER "G_STRUCT_OFFSET(%s," SECTION(strings) ") + %d"
+
+/* Parameters(To the string)
+ * Metatada struct name
+ * Type name
+ */
+#define TYPE_POINTER "G_STRUCT_OFFSET(%s,"ID_TO_ENTRY")"
+
+#endif /*__G_IDL_COMPILER_CONTEXT_H__*/
Added: trunk/tools/gidlcompilerentrynode.c
==============================================================================
--- (empty file)
+++ trunk/tools/gidlcompilerentrynode.c Mon Mar 10 17:45:59 2008
@@ -0,0 +1,1266 @@
+/* GObject introspection: Node compilation
+ *
+ * Copyright (C) 2005 Matthias Clasen
+ * Copyright (C) 2008 Codethink Ltd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "gmetadata.h"
+
+#include "gidlnode.h"
+#include "gidlmodule.h"
+#include "gidlcompilercontext.h"
+#include "gidlcompilertypenode.h"
+
+/* PARAMETER BLOB COMPILATION */
+/*----------------------------*/
+/* Blobs in this section do not get a directory entry.
+ * They are not types in themselves but are just information
+ * about types, such as the signals of an object or the fields
+ * of a struct.
+ */
+
+/*VALUE*/
+/* Used in enums and flags */
+static void
+include_value (GIdlNode * node, GIdlCompilerContext * ctx)
+{
+ GIdlNodeValue *value = (GIdlNodeValue *) node;
+ const gchar *value_prototype = " {%d, %d, " STRING_POINTER ", %d},\n";
+
+ fprintf (ctx->mdata_init, value_prototype,
+ value->deprecated,
+ 0,
+ ctx->struct_name, g_idl_compiler_write_string (ctx, node->name),
+ value->value);
+}
+
+/*PARAM*/
+/* Used in signatures */
+static void
+include_param (GIdlNode * node, GIdlCompilerContext * ctx)
+{
+ GIdlNodeParam *param = (GIdlNodeParam *) node;
+
+ const gchar *param_header =
+ " {\n"
+ " "STRING_POINTER",\n"
+ " %d, %d, %d, %d, %d, %d, %d, %d, 0,\n";
+
+ fprintf (ctx->mdata_init, param_header,
+ ctx->struct_name, g_idl_compiler_write_string (ctx, node->name),
+ param->in,
+ param->out,
+ param->dipper,
+ param->null_ok,
+ param->optional,
+ param->transfer,
+ param->shallow_transfer,
+ param->retval);
+
+ g_idl_compiler_write_simple_type_blob ((GIdlNode *)param->type, ctx);
+
+ fprintf(ctx->mdata_init, " },\n");
+}
+
+/*V FUNC*/
+/* Used in objects and interfaces */
+static void
+include_vfunc (GIdlNode * node, GIdlCompilerContext * ctx)
+{
+ guint signature_id;
+ GIdlNodeVFunc *vfunc = (GIdlNodeVFunc *) node;
+ const char *vfunc_header =
+ " {\n"
+ " "STRING_POINTER",\n"
+ " %d, %d, %d, %d, 0, %d,\n"
+ " %d, 0,\n"
+ " "TYPE_POINTER",\n"
+ " },\n";
+
+ signature_id = g_idl_compiler_get_unique_id();
+
+ g_idl_compiler_push_deferred_signature_node(ctx, node, signature_id);
+
+ fprintf(ctx->mdata_init, vfunc_header,
+ ctx->struct_name, g_idl_compiler_write_string (ctx, node->name),
+ 0, /*FIXME*/
+ 0, /*FIXME*/
+ 0, /*FIXME*/
+ 0, /*FIXME*/
+ 0, /*FIXME*/
+ vfunc->offset,
+ ctx->struct_name, signature_id);
+}
+
+/*PROPERTY*/
+/* Used in objects and interfaces */
+static void
+include_property (GIdlNode * node, GIdlCompilerContext * ctx)
+{
+ GIdlNodeProperty *property = (GIdlNodeProperty *) node;
+
+ const gchar *property_header =
+ " {\n"
+ " "STRING_POINTER", %d, %d, %d, %d, %d, 0,\n";
+
+ fprintf (ctx->mdata_init, property_header,
+ ctx->struct_name, g_idl_compiler_write_string (ctx, node->name),
+ property->deprecated,
+ property->readable,
+ property->writable,
+ property->construct,
+ property->construct_only);
+
+ /*Insert simple type blob here */
+ g_idl_compiler_write_simple_type_blob ((GIdlNode *)property->type, ctx);
+
+ fprintf (ctx->mdata_init, " },\n");
+}
+
+/*FIELD*/
+/* Used in struct */
+static void
+include_field (GIdlNode * node, GIdlCompilerContext * ctx)
+{
+ GIdlNodeField *field = (GIdlNodeField *) node;
+
+ const gchar *field_header =
+ " {\n"
+ " "STRING_POINTER", %d, %d, %d, %d, %d,\n";
+
+ fprintf (ctx->mdata_init, field_header,
+ ctx->struct_name, g_idl_compiler_write_string (ctx, node->name),
+ field->readable, field->writable, 0, 0, field->offset);
+
+ /*Insert simple type blob here */
+ g_idl_compiler_write_simple_type_blob ((GIdlNode *)field->type, ctx);
+
+ fprintf (ctx->mdata_init, " },\n");
+}
+
+ /*SIGNAL*/
+/* Used in interface and object */
+static void
+include_signal (GIdlNode * node, GIdlCompilerContext * ctx)
+{
+ guint signature_id;
+ GIdlNodeSignal *signal = (GIdlNodeSignal *) node;
+ const char *signal_header =
+ " {\n"
+ " %d, %d, %d, %d, %d,\n"
+ " %d, %d, %d, %d, %d,\n"
+ " 0,\n"
+ " %d,\n"
+ " "STRING_POINTER",\n"
+ " "TYPE_POINTER",\n"
+ " },\n";
+
+ signature_id = g_idl_compiler_get_unique_id();
+
+ g_idl_compiler_push_deferred_signature_node(ctx, node, signature_id);
+
+ fprintf(ctx->mdata_init, signal_header,
+ signal->deprecated,
+ signal->run_first,
+ signal->run_last,
+ signal->run_cleanup,
+ signal->no_recurse,
+ signal->detailed,
+ signal->action,
+ signal->no_hooks,
+ 0, /*FIXME*/
+ 0, /*FIXME*/
+ 0, /*FIXME*/
+ ctx->struct_name, g_idl_compiler_write_string (ctx, node->name),
+ ctx->struct_name, signature_id);
+}
+
+/*METHOD*/
+/*Used in struct object interface, uses the FunctionBlob*/
+static void
+include_method (GIdlNode * node,
+ GIdlCompilerContext * ctx)
+{
+ guint signature_id;
+ GIdlNodeFunction *function = (GIdlNodeFunction *) node;
+ const char *function_header =
+ " {\n"
+ " %d, %d, %d, %d, %d, %d, 0, %d,\n"
+ " "STRING_POINTER",\n"
+ " "STRING_POINTER",\n"
+ " "TYPE_POINTER",\n"
+ " },\n";
+
+ signature_id = g_idl_compiler_get_unique_id();
+
+ g_idl_compiler_push_deferred_signature_node(ctx, node, signature_id);
+
+ fprintf(ctx->mdata_init, function_header,
+ BLOB_TYPE_FUNCTION,
+ function->deprecated,
+ function->is_setter,
+ function->is_getter,
+ function->is_constructor,
+ function->wraps_vfunc,
+ 0, /*index??*/
+ ctx->struct_name, g_idl_compiler_write_string (ctx, node->name),
+ ctx->struct_name, g_idl_compiler_write_string (ctx, function->symbol),
+ ctx->struct_name, signature_id);
+}
+
+/*CONSTANT*/
+static void
+include_constant (GIdlNode * node,
+ GIdlCompilerContext * ctx)
+{
+ GIdlNodeConstant *constant = (GIdlNodeConstant *)node;
+ guint entry_id;
+ const gchar *constant_header =
+ " {\n"
+ " %d, %d, 0,\n" /*type/deprecated/reserved */
+ " "STRING_POINTER",\n"; /*name */
+
+ const gchar *constant_footer =
+ " %d, "TYPE_POINTER"\n" /*size/offset*/
+ " },\n";
+
+ fprintf (ctx->mdata_init, constant_header,
+ BLOB_TYPE_CONSTANT,
+ constant->deprecated,
+ ctx->struct_name, g_idl_compiler_write_string (ctx, node->name));
+
+ g_idl_compiler_write_simple_type_blob ((GIdlNode *)constant->type, ctx);
+
+ entry_id = g_idl_compiler_get_unique_id();
+
+ g_idl_compiler_push_deferred_constant(ctx, node, entry_id);
+
+ fprintf (ctx->mdata_init, constant_footer,
+ 0, /*FIXME I'm excluding the size, where is this used?*/
+ ctx->struct_name, entry_id);
+}
+
+/*ENTRY BLOB COMPILATION*/
+/*----------------------*/
+/* Blobs in this section are given a directory entry
+ * and can be used as a type
+ */
+
+/*ENUM / FLAGS*/
+static void
+write_enum (GIdlNode * node,
+ guint entry_id,
+ GIdlCompilerContext * ctx)
+{
+ GIdlNodeEnum *enum_ = (GIdlNodeEnum *) node;
+ guint16 blob_type;
+ guint32 gtype_name = 0;
+ guint32 gtype_init = 0;
+ guint unregistered;
+ GList *c;
+
+ const gchar *enum_flags_struct =
+ " struct\n"
+ " {\n"
+ " EnumBlob fixed;\n"
+ " ValueBlob values[%d];\n"
+ " } " ID_TO_ENTRY ";\n";
+
+ const gchar *enum_flags_header =
+ " {\n"
+ " {\n"
+ " %d, %d, %d, %d,\n" /*type/deprecated/unregistered/reserved */
+ " " STRING_POINTER ",\n" /*name */
+ " " STRING_POINTER ",\n" /*gtype-name */
+ " " STRING_POINTER ",\n" /*gtype-init */
+ " %d, %d\n" " },\n"; /*n_values/reserved */
+
+ if (node->type == G_IDL_NODE_ENUM)
+ blob_type = BLOB_TYPE_ENUM;
+ else
+ blob_type = BLOB_TYPE_FLAGS;
+
+ if (enum_->gtype_name)
+ {
+ unregistered = FALSE;
+ gtype_name = g_idl_compiler_write_string (ctx, enum_->gtype_name);
+ gtype_init = g_idl_compiler_write_string (ctx, enum_->gtype_init);
+ }
+ else
+ {
+ unregistered = TRUE;
+ gtype_name = 0;
+ gtype_init = 0;
+ }
+
+ fprintf (ctx->mdata_struct, enum_flags_struct,
+ g_list_length (enum_->values), entry_id);
+
+ fprintf (ctx->mdata_init, enum_flags_header,
+ blob_type,
+ enum_->deprecated,
+ unregistered,
+ 0,
+ ctx->struct_name, g_idl_compiler_write_string (ctx, node->name),
+ ctx->struct_name, gtype_name,
+ ctx->struct_name, gtype_init, g_list_length (enum_->values), 0);
+
+ /*Insert value initialisers here */
+ fprintf (ctx->mdata_init, " {\n");
+ for (c = enum_->values; c; c = c->next)
+ {
+ include_value (c->data, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ fprintf (ctx->mdata_init, " },\n\n");
+}
+
+/*FUNCTION*/
+static void
+write_function (GIdlNode * node,
+ guint entry_id,
+ GIdlCompilerContext * ctx)
+{
+ const char *function_struct =
+ " FunctionBlob "ID_TO_ENTRY";\n";
+
+ fprintf(ctx->mdata_struct, function_struct, entry_id);
+
+ include_method(node, ctx);
+}
+
+/*SIGNATURE*/
+static void
+write_signature (GIdlNode * node,
+ guint entry_id,
+ GIdlCompilerContext * ctx)
+{
+ GList *c;
+ GIdlNodeFunction *function = (GIdlNodeFunction *) node;
+ GIdlNodeVFunc *vfunc = (GIdlNodeVFunc *) node;
+ GIdlNodeSignal *signal = (GIdlNodeSignal *) node;
+ guint n_args;
+ GIdlNodeType *result_type;
+ guint null_ok;
+ guint transfer;
+ guint shallow_transfer;
+ GList *param_list;
+
+ const char *signature_struct =
+ " struct\n"
+ " {\n"
+ " SignatureBlob fixed;\n"
+ " ArgBlob values[%d];\n"
+ " } " ID_TO_ENTRY ";\n";
+
+ const char *signature_prototype =
+ " %d, %d, %d, 0, %d,\n";
+
+ switch (node->type)
+ {
+ case G_IDL_NODE_CALLBACK:
+ case G_IDL_NODE_FUNCTION:
+ null_ok = function->result->null_ok,
+ transfer = function->result->transfer,
+ shallow_transfer = function->result->shallow_transfer,
+ param_list = function->parameters;
+ result_type = function->result->type;
+ break;
+ case G_IDL_NODE_VFUNC:
+ null_ok = vfunc->result->null_ok,
+ transfer = vfunc->result->transfer,
+ shallow_transfer = vfunc->result->shallow_transfer,
+ param_list = vfunc->parameters;
+ result_type = vfunc->result->type;
+ break;
+ case G_IDL_NODE_SIGNAL:
+ null_ok = signal->result->null_ok,
+ transfer = signal->result->transfer,
+ shallow_transfer = signal->result->shallow_transfer,
+ param_list = signal->parameters;
+ result_type = signal->result->type;
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+
+ n_args = g_list_length(param_list);
+
+ fprintf(ctx->mdata_struct, signature_struct, n_args, entry_id);
+
+ fprintf(ctx->mdata_init, " {\n");
+ fprintf(ctx->mdata_init, " {\n");
+
+ g_idl_compiler_write_simple_type_blob ((GIdlNode *)result_type, ctx);
+
+ fprintf(ctx->mdata_init, signature_prototype,
+ null_ok,
+ transfer,
+ shallow_transfer,
+ n_args);
+
+ fprintf (ctx->mdata_init, " },\n");
+
+ /*Write out all the args*/
+ fprintf (ctx->mdata_init, " {\n");
+ for (c = param_list; c; c = c->next)
+ {
+ include_param (c->data, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ fprintf(ctx->mdata_init, " },\n\n");
+}
+
+/*CALLBACK*/
+static void
+write_callback (GIdlNode * node,
+ guint entry_id,
+ GIdlCompilerContext * ctx)
+{
+ guint signature_id;
+ GIdlNodeFunction *function = (GIdlNodeFunction *) node;
+
+ const char *callback_struct =
+ " CallbackBlob "ID_TO_ENTRY";\n";
+
+ const char *callback_header =
+ " {\n"
+ " %d, %d, 0,\n"
+ " "STRING_POINTER",\n"
+ " "TYPE_POINTER",\n"
+ " },\n";
+
+ fprintf(ctx->mdata_struct, callback_struct, entry_id);
+
+ signature_id = g_idl_compiler_get_unique_id();
+
+ g_idl_compiler_push_deferred_signature_node(ctx, node, signature_id);
+
+ fprintf(ctx->mdata_init, callback_header,
+ BLOB_TYPE_CALLBACK,
+ function->deprecated,
+ ctx->struct_name, g_idl_compiler_write_string (ctx, node->name),
+ ctx->struct_name, signature_id);
+}
+
+/*BOXED*/
+/*TODO merge the boxed and struct functions.*/
+static void
+write_boxed (GIdlNode * node,
+ guint entry_id,
+ GIdlCompilerContext * ctx)
+{
+ GIdlNodeBoxed *boxed = (GIdlNodeBoxed *) node;
+ guint16 n_method = 0;
+ guint16 n_field = 0;
+ GList *l;
+
+ const char *struct_struct =
+ " struct\n"
+ " {\n"
+ " StructBlob fixed;\n"
+ " FieldBlob fields[%d];\n"
+ " FunctionBlob methods[%d];\n"
+ " } " ID_TO_ENTRY ";\n";
+
+ const gchar *struct_header =
+ " {\n"
+ " {\n"
+ " %d, %d, %d, %d,\n" /*type/deprecated/unregistered/reserved */
+ " " STRING_POINTER ",\n" /*name */
+ " " STRING_POINTER ",\n" /*gtype-name */
+ " " STRING_POINTER ",\n" /*gtype-init */
+ " %d, %d\n" /*n_fields/n_methods */
+ " },\n"; /*n_values/reserved */
+
+ for (l = boxed->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_FIELD)
+ {
+ n_field++;
+ }
+ else
+ {
+ n_method++;
+ }
+ }
+
+ fprintf (ctx->mdata_struct, struct_struct, n_field, n_method, entry_id);
+
+ fprintf (ctx->mdata_init, struct_header,
+ BLOB_TYPE_STRUCT,
+ boxed->deprecated,
+ FALSE,
+ 0,
+ ctx->struct_name, g_idl_compiler_write_string (ctx, node->name),
+ ctx->struct_name, g_idl_compiler_write_string (ctx, boxed->gtype_name),
+ ctx->struct_name, g_idl_compiler_write_string (ctx, boxed->gtype_init),
+ n_field, n_method);
+
+ /*Insert field initialisers here */
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = boxed->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_FIELD)
+ include_field (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ /*Insert method initialisers here */
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = boxed->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_FUNCTION)
+ include_method (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ fprintf (ctx->mdata_init, " },\n\n");
+}
+
+/*STRUCT*/
+static void
+write_struct (GIdlNode * node,
+ guint entry_id,
+ GIdlCompilerContext * ctx)
+{
+ GIdlNodeStruct *struct_ = (GIdlNodeStruct *) node;
+ guint16 n_method = 0;
+ guint16 n_field = 0;
+ GList *l;
+
+ const char *struct_struct =
+ " struct\n"
+ " {\n"
+ " StructBlob fixed;\n"
+ " FieldBlob fields[%d];\n"
+ " FunctionBlob methods[%d];\n"
+ " } " ID_TO_ENTRY ";\n";
+
+ const gchar *struct_header =
+ " {\n"
+ " {\n"
+ " %d, %d, %d, %d,\n" /*type/deprecated/unregistered/reserved */
+ " " STRING_POINTER ",\n" /*name */
+ " " STRING_POINTER ",\n" /*gtype-name */
+ " " STRING_POINTER ",\n" /*gtype-init */
+ " %d, %d\n" /*n_fields/n_methods */
+ " },\n"; /*n_values/reserved */
+
+ for (l = struct_->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_FIELD)
+ {
+ n_field++;
+ }
+ else
+ {
+ n_method++;
+ }
+ }
+
+ fprintf (ctx->mdata_struct, struct_struct, n_field, n_method, entry_id);
+
+ fprintf (ctx->mdata_init, struct_header,
+ BLOB_TYPE_STRUCT,
+ struct_->deprecated,
+ TRUE,
+ 0,
+ ctx->struct_name, g_idl_compiler_write_string (ctx, node->name),
+ ctx->struct_name, 0, ctx->struct_name, 0, n_field, n_method);
+
+ /*Insert field initialisers here */
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = struct_->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_FIELD)
+ include_field (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ /*Insert method initialisers here */
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = struct_->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_FUNCTION)
+ include_method (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ fprintf (ctx->mdata_init, " },\n\n");
+}
+
+/*UNION*/
+static void
+write_union (GIdlNode * node,
+ guint entry_id,
+ GIdlCompilerContext * ctx)
+{
+ GIdlNodeUnion *union_ = (GIdlNodeUnion *)node;
+ guint16 n_method = 0;
+ guint16 n_field = 0;
+ guint16 n_constant = 0;
+ gboolean discriminated = FALSE;
+ gboolean unregistered = TRUE;
+ GList *l;
+
+ const char *union_struct =
+ " struct\n"
+ " {\n"
+ " UnionBlob fixed;\n"
+ " FieldBlob fields[%d];\n"
+ " FunctionBlob methods[%d];\n"
+ " ConstantBlob discriminator_values[%d];\n"
+ " } " ID_TO_ENTRY ";\n";
+
+ const gchar *union_header =
+ " {\n"
+ " {\n"
+ " %d, %d, %d, %d, 0,\n" /*type/deprecated/unregistered/descriminated */
+ " " STRING_POINTER ",\n" /*name */
+ " " STRING_POINTER ",\n" /*gtype-name */
+ " " STRING_POINTER ",\n" /*gtype-init */
+ " %d, %d,\n" /*n_fields/n_methods */
+ " %d,\n"; /*discriminator_offset*/
+
+ for (l = union_->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_FIELD)
+ {
+ n_field++;
+ }
+ else
+ {
+ n_method++;
+ }
+ }
+
+ if (union_->discriminator_type)
+ {
+ discriminated = TRUE;
+ n_constant = g_list_length(union_->discriminators);
+ }
+
+ if (union_->gtype_name)
+ {
+ unregistered = FALSE;
+ }
+
+ fprintf (ctx->mdata_struct, union_struct, n_field, n_method, n_constant, entry_id);
+
+ fprintf (ctx->mdata_init, union_header,
+ BLOB_TYPE_UNION,
+ union_->deprecated,
+ unregistered,
+ discriminated,
+ ctx->struct_name, g_idl_compiler_write_string (ctx, node->name),
+ ctx->struct_name, g_idl_compiler_write_string (ctx, union_->gtype_name),
+ ctx->struct_name, g_idl_compiler_write_string (ctx, union_->gtype_init),
+ n_field, n_method,
+ union_->discriminator_offset);
+
+ if (discriminated)
+ {
+ g_idl_compiler_write_simple_type_blob ((GIdlNode *)union_->discriminator_type, ctx);
+ }
+ else
+ {
+ fprintf (ctx->mdata_init, " {},\n");
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ /*Insert field initialisers here */
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = union_->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_FIELD)
+ include_field (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ /*Insert method initialisers here */
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = union_->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_FUNCTION)
+ include_method (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ /*Insert discriminators here*/
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = union_->discriminators; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ include_constant (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ fprintf (ctx->mdata_init, " },\n\n");
+}
+
+/*OBJECT*/
+static void
+write_object (GIdlNode * node,
+ guint entry_id,
+ GIdlCompilerContext * ctx)
+{
+ GIdlNodeInterface *object = (GIdlNodeInterface *) node;
+ guint num_interfaces = 0;
+ guint num_fields = 0;
+ guint num_properties = 0;
+ guint num_methods = 0;
+ guint num_signals = 0;
+ guint num_vfuncs = 0;
+ guint num_constants = 0;
+
+ GList *l;
+
+ const char *object_struct =
+ " struct\n"
+ " {\n"
+ " ObjectBlob fixed;\n"
+ " guint16 interfaces[%d];\n"
+ " FieldBlob fields[%d];\n"
+ " PropertyBlob properties[%d];\n"
+ " FunctionBlob methods[%d];\n"
+ " SignalBlob signals[%d];\n"
+ " VFuncBlob vfuncs[%d];\n"
+ " ConstantBlob constants[%d];\n"
+ " } " ID_TO_ENTRY ";\n";
+
+ const gchar *object_header =
+ " {\n"
+ " {\n"
+ " %d, %d, 0,\n"
+ " " STRING_POINTER ",\n"
+ " " STRING_POINTER ",\n"
+ " " STRING_POINTER ",\n";
+
+ const gchar *object_footer =
+ " %d, %d, %d, %d, %d, %d, %d,\n"
+ " },\n";
+
+ const gchar *type_entry =
+ " %d,\n";
+
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ switch (tnode->type)
+ {
+ case G_IDL_NODE_FIELD:
+ num_fields++;
+ break;
+ case G_IDL_NODE_PROPERTY:
+ num_properties++;
+ break;
+ case G_IDL_NODE_FUNCTION:
+ num_methods++;
+ break;
+ case G_IDL_NODE_SIGNAL:
+ num_signals++;
+ break;
+ case G_IDL_NODE_VFUNC:
+ num_vfuncs++;
+ break;
+ case G_IDL_NODE_CONSTANT:
+ num_constants++;
+ break;
+ default:
+ ;
+ }
+ }
+
+ num_interfaces = g_list_length(object->interfaces);
+
+ fprintf(ctx->mdata_struct, object_struct,
+ num_interfaces,
+ num_fields,
+ num_properties,
+ num_methods,
+ num_signals,
+ num_vfuncs,
+ num_constants,
+ entry_id);
+
+ fprintf (ctx->mdata_init, object_header,
+ BLOB_TYPE_INTERFACE,
+ object->deprecated,
+ ctx->struct_name, g_idl_compiler_write_string (ctx, node->name),
+ ctx->struct_name, g_idl_compiler_write_string (ctx, object->gtype_name),
+ ctx->struct_name, g_idl_compiler_write_string (ctx, object->gtype_init));
+
+ if (object->parent)
+ {
+ fprintf(ctx->mdata_init, type_entry,
+ g_idl_compiler_get_entry_dirid(ctx, object->parent));
+ }
+ else
+ {
+ fprintf (ctx->mdata_init, " 0,\n");
+ }
+
+ fprintf (ctx->mdata_init, object_footer,
+ num_interfaces,
+ num_fields,
+ num_properties,
+ num_methods,
+ num_signals,
+ num_vfuncs,
+ num_constants);
+
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = object->interfaces; l; l = l->next)
+ {
+ gchar *interface = l->data;
+ fprintf(ctx->mdata_init, type_entry,
+ g_idl_compiler_get_entry_dirid(ctx, interface));
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ /*Insert fields here*/
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_FIELD)
+ include_field (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ /*Insert properties here*/
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_PROPERTY)
+ include_property (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ /*Insert functions here*/
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_FUNCTION)
+ include_method (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ /*Insert signals here*/
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_SIGNAL)
+ include_signal (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ /*Insert vfuncs here*/
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_VFUNC)
+ include_vfunc (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ /*Insert constants here*/
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_CONSTANT)
+ include_constant (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ fprintf (ctx->mdata_init, " },\n\n");
+}
+
+/*INTERFACE*/
+static void
+write_interface(GIdlNode * node,
+ guint entry_id,
+ GIdlCompilerContext * ctx)
+{
+ GIdlNodeInterface *iface = (GIdlNodeInterface *) node;
+ guint num_prerequisites = 0;
+ guint num_properties = 0;
+ guint num_methods = 0;
+ guint num_signals = 0;
+ guint num_vfuncs = 0;
+ guint num_constants = 0;
+
+ GList *l;
+
+ const char *interface_struct =
+ " struct\n"
+ " {\n"
+ " InterfaceBlob fixed;\n"
+ " guint16 prerequisites[%d];\n"
+ " PropertyBlob properties[%d];\n"
+ " FunctionBlob methods[%d];\n"
+ " SignalBlob signals[%d];\n"
+ " VFuncBlob vfuncs[%d];\n"
+ " ConstantBlob constants[%d];\n"
+ " } " ID_TO_ENTRY ";\n";
+
+ const gchar *interface_header =
+ " {\n"
+ " {\n"
+ " %d, %d, 0,\n"
+ " " STRING_POINTER ",\n"
+ " " STRING_POINTER ",\n"
+ " " STRING_POINTER ",\n"
+ " %d, %d, %d, %d, %d, %d,\n"
+ " },\n";
+
+ const gchar *prereq_entry =
+ " %d,\n";
+
+ for (l = iface->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ switch (tnode->type)
+ {
+ case G_IDL_NODE_PROPERTY:
+ num_properties++;
+ break;
+ case G_IDL_NODE_FUNCTION:
+ num_methods++;
+ break;
+ case G_IDL_NODE_SIGNAL:
+ num_signals++;
+ break;
+ case G_IDL_NODE_VFUNC:
+ num_vfuncs++;
+ break;
+ case G_IDL_NODE_CONSTANT:
+ num_constants++;
+ break;
+ default:
+ ;
+ }
+ }
+
+ num_prerequisites = g_list_length(iface->prerequisites);
+
+ fprintf(ctx->mdata_struct, interface_struct,
+ num_prerequisites,
+ num_properties,
+ num_methods,
+ num_signals,
+ num_vfuncs,
+ num_constants,
+ entry_id);
+
+ fprintf (ctx->mdata_init, interface_header,
+ BLOB_TYPE_INTERFACE,
+ iface->deprecated,
+ ctx->struct_name, g_idl_compiler_write_string (ctx, node->name),
+ ctx->struct_name, g_idl_compiler_write_string (ctx, iface->gtype_name),
+ ctx->struct_name, g_idl_compiler_write_string (ctx, iface->gtype_init),
+ num_prerequisites,
+ num_properties,
+ num_methods,
+ num_signals,
+ num_vfuncs,
+ num_constants);
+
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = iface->prerequisites; l; l = l->next)
+ {
+ gchar *prereq = l->data;
+ fprintf(ctx->mdata_init, prereq_entry,
+ g_idl_compiler_get_entry_dirid(ctx, prereq));
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ /*Insert properties here*/
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = iface->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_PROPERTY)
+ include_property (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ /*Insert functions here*/
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = iface->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_FUNCTION)
+ include_method (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ /*Insert signals here*/
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = iface->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_SIGNAL)
+ include_signal (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ /*Insert vfuncs here*/
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = iface->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_VFUNC)
+ include_vfunc (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ /*Insert constants here*/
+ fprintf (ctx->mdata_init, " {\n");
+ for (l = iface->members; l; l = l->next)
+ {
+ GIdlNode *tnode = l->data;
+ if (tnode->type == G_IDL_NODE_CONSTANT)
+ include_constant (tnode, ctx);
+ }
+ fprintf (ctx->mdata_init, " },\n");
+
+ fprintf (ctx->mdata_init, " },\n\n");
+}
+
+/*ERROR DOMAIN*/
+static void
+write_error_domain (GIdlNode * node,
+ guint entry_id,
+ GIdlCompilerContext * ctx)
+{
+ GIdlNodeErrorDomain *domain = (GIdlNodeErrorDomain *) node;
+ const char *error_domain_struct =
+ " ErrorDomainBlob " ID_TO_ENTRY ";\n";
+
+ const gchar *error_domain_header =
+ " {\n"
+ " %d, %d, 0,\n"
+ " " STRING_POINTER ",\n" /*name */
+ " " STRING_POINTER ",\n" /*get-quark */
+ " " TYPE_POINTER ",\n" /*error-codes*/
+ " 0,\n"
+ " },\n\n";
+
+ fprintf(ctx->mdata_struct, error_domain_struct, entry_id);
+
+ fprintf(ctx->mdata_init, error_domain_header,
+ BLOB_TYPE_ERROR_DOMAIN,
+ domain->deprecated,
+ ctx->struct_name, g_idl_compiler_write_string (ctx, node->name),
+ ctx->struct_name, g_idl_compiler_write_string (ctx, domain->getquark),
+ ctx->struct_name, g_idl_compiler_get_entry_id (ctx, domain->codes));
+}
+
+/*CONSTANT*/
+static void
+write_constant (GIdlNode * node,
+ guint entry_id,
+ GIdlCompilerContext * ctx)
+{
+ const char *constant_struct =
+ " ConstantBlob " ID_TO_ENTRY ";\n";
+
+ fprintf(ctx->mdata_struct, constant_struct, entry_id);
+
+ include_constant(node, ctx);
+}
+
+static void
+write_deferred_constant_values(GIdlCompilerContext *ctx)
+{
+ /* TODO there are very few symbols that can be represented
+ * as a constant, do we check if something is awry here
+ * to prevent errors at compilation time?
+ */
+ GIdlNodeConstant *constant;
+ guint entry_id;
+ gchar *type_string;
+
+ const char *cvalue_struct =
+ " %s " ID_TO_ENTRY ";\n";
+
+ const char *cvalue_str_struct =
+ " gchar *" ID_TO_ENTRY ";\n";
+
+ constant = (GIdlNodeConstant *) g_idl_compiler_pop_deferred_constant(ctx, &entry_id);
+ while (constant != NULL)
+ {
+ fprintf(ctx->mdata_init, " /*Entry - %d*/\n",
+ entry_id);
+ if (constant->type->tag <= TYPE_TAG_DOUBLE)
+ {
+ fprintf(ctx->mdata_struct, cvalue_struct,
+ g_idl_compiler_name_basic_type(constant->type->tag),
+ entry_id);
+ fprintf(ctx->mdata_init, " %s,\n",
+ constant->value);
+ }
+ else if (constant->type->tag <= TYPE_TAG_FILENAME)
+ {
+ fprintf(ctx->mdata_struct, cvalue_str_struct,
+ entry_id);
+ fprintf(ctx->mdata_init, " \"%s\",\n",
+ constant->value);
+ }
+ else if (constant->type->tag <= TYPE_TAG_SYMBOL)
+ {
+ GString *str;
+ gchar *s;
+
+ str = g_string_new (0);
+ g_idl_compiler_serialize_type (constant->type, str);
+ s = g_string_free (str, FALSE);
+
+ fprintf(ctx->mdata_struct, cvalue_struct,
+ s,
+ entry_id);
+ fprintf(ctx->mdata_init, " \"%s\",\n",
+ constant->value);
+ g_free(s);
+ }
+ else
+ {
+ g_warning("Cannot write constant value");
+ }
+ constant = (GIdlNodeConstant *) g_idl_compiler_pop_deferred_constant(ctx, &entry_id);
+ }
+}
+
+static void
+write_deferred_signature_nodes(GIdlCompilerContext *ctx)
+{
+ GIdlNode *node;
+ guint entry_id;
+
+ node = g_idl_compiler_pop_deferred_signature_node(ctx, &entry_id);
+ while (node != NULL)
+ {
+ fprintf(ctx->mdata_init, " /*Entry - %d*/\n",
+ entry_id);
+ write_signature(node, entry_id, ctx);
+ node = g_idl_compiler_pop_deferred_signature_node(ctx, &entry_id);
+ }
+}
+
+void
+g_idl_compiler_write_node (GIdlNode * node,
+ guint entry_id, GIdlCompilerContext * ctx)
+{
+ GList *l;
+
+ fprintf(ctx->mdata_init, " /*Entry - %d*/\n",
+ entry_id);
+
+ switch (node->type)
+ {
+ case G_IDL_NODE_FUNCTION:
+ {
+ write_function (node, entry_id, ctx);
+ }
+ break;
+
+ case G_IDL_NODE_CALLBACK:
+ {
+ write_callback (node, entry_id, ctx);
+ }
+ break;
+
+ case G_IDL_NODE_STRUCT:
+ {
+ write_struct (node, entry_id, ctx);
+ }
+ break;
+
+ case G_IDL_NODE_BOXED:
+ {
+ write_boxed (node, entry_id, ctx);
+ }
+ break;
+
+ case G_IDL_NODE_UNION:
+ {
+ write_union (node, entry_id, ctx);
+ }
+ break;
+
+ case G_IDL_NODE_ENUM:
+ case G_IDL_NODE_FLAGS:
+ {
+ write_enum (node, entry_id, ctx);
+ }
+ break;
+
+ case G_IDL_NODE_OBJECT:
+ {
+ write_object (node, entry_id, ctx);
+ }
+ break;
+
+ case G_IDL_NODE_INTERFACE:
+ {
+ write_interface (node, entry_id, ctx);
+ }
+ break;
+
+ case G_IDL_NODE_ERROR_DOMAIN:
+ {
+ write_error_domain (node, entry_id, ctx);
+ }
+ break;
+
+ case G_IDL_NODE_CONSTANT:
+ {
+ write_constant (node, entry_id, ctx);
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ write_deferred_constant_values(ctx);
+ write_deferred_signature_nodes(ctx);
+ g_idl_compiler_write_deferred_type_blobs(ctx);
+}
Added: trunk/tools/gidlcompilerentrynode.h
==============================================================================
--- (empty file)
+++ trunk/tools/gidlcompilerentrynode.h Mon Mar 10 17:45:59 2008
@@ -0,0 +1,37 @@
+/* GObject introspection: Parsed IDL
+ *
+ * Copyright (C) 2008 Codethink Ltd
+ *
+ * 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_COMP_ENTRY_N_H__
+#define __G_IDL_COMP_ENTRY_N_H__
+
+#include <glib.h>
+
+#include "gidlnode.h"
+#include "gidlcompilercontext.h"
+
+G_BEGIN_DECLS
+
+void
+g_idl_compiler_write_node (GIdlNode * node,
+ guint entry_id,
+ GIdlCompilerContext * ctx);
+
+G_END_DECLS
+#endif /* __G_IDL_COMP_ENTRY_N_H__ */
Added: trunk/tools/gidlcompilertypenode.c
==============================================================================
--- (empty file)
+++ trunk/tools/gidlcompilertypenode.c Mon Mar 10 17:45:59 2008
@@ -0,0 +1,430 @@
+/* GObject introspection: Type node compilation
+ *
+ * Copyright (C) 2005 Matthias Clasen
+ * Copyright (C) 2008 Codethink Ltd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "gmetadata.h"
+
+#include "gidlnode.h"
+#include "gidlcompilercontext.h"
+#include "gidlcompilertypenode.h"
+
+/*TYPE BLOB COMPILATION*/
+/*---------------------*/
+
+const gchar *
+g_idl_compiler_name_basic_type(guint type_tag)
+{
+ const gchar *basic[] = {
+ "void",
+ "gboolean",
+ "gint8",
+ "guint8",
+ "gint16",
+ "guint16",
+ "gint32",
+ "guint32",
+ "gint64",
+ "guint64",
+ "gint",
+ "guint",
+ "glong",
+ "gulong",
+ "gssize",
+ "gsize",
+ "gfloat",
+ "gdouble",
+ "utf8",
+ "filename"
+ };
+
+ return basic[type_tag];
+}
+
+void
+g_idl_compiler_serialize_type (GIdlNodeType * node, GString * str)
+{
+ gint i;
+
+ if (TYPE_IS_SIMPLE(node->tag))
+ {
+ g_string_append_printf (str, "%s%s",
+ g_idl_compiler_name_basic_type(node->tag),
+ node->is_pointer ? "*" : "");
+ }
+ else if (node->tag == TYPE_TAG_ARRAY)
+ {
+ g_idl_compiler_serialize_type (node->parameter_type1, str);
+ g_string_append (str, "[");
+
+ if (node->has_length)
+ g_string_append_printf (str, "length=%d", node->length);
+
+ if (node->zero_terminated)
+ g_string_append_printf (str, "%szero-terminated=1",
+ node->has_length ? "," : "");
+
+ g_string_append (str, "]");
+ }
+ else if (node->tag == TYPE_TAG_SYMBOL)
+ {
+ g_string_append_printf (str, "%s%s", node->interface,
+ node->is_pointer ? "*" : "");
+ }
+ else if (node->tag == TYPE_TAG_LIST)
+ {
+ g_string_append (str, "GList");
+ if (node->parameter_type1)
+ {
+ g_string_append (str, "<");
+ g_idl_compiler_serialize_type (node->parameter_type1, str);
+ g_string_append (str, ">");
+ }
+ }
+ else if (node->tag == TYPE_TAG_SLIST)
+ {
+ g_string_append (str, "GSList");
+ if (node->parameter_type1)
+ {
+ g_string_append (str, "<");
+ g_idl_compiler_serialize_type (node->parameter_type1, str);
+ g_string_append (str, ">");
+ }
+ }
+ else if (node->tag == TYPE_TAG_HASH)
+ {
+ g_string_append (str, "GHashTable<");
+ if (node->parameter_type1)
+ {
+ g_string_append (str, "<");
+ g_idl_compiler_serialize_type (node->parameter_type1, str);
+ g_string_append (str, ",");
+ g_idl_compiler_serialize_type (node->parameter_type2, str);
+ g_string_append (str, ">");
+ }
+ }
+ else if (node->tag == TYPE_TAG_ERROR)
+ {
+ g_string_append (str, "GError");
+ if (node->errors)
+ {
+ g_string_append (str, "<");
+ for (i = 0; node->errors[i]; i++)
+ {
+ if (i > 0)
+ g_string_append (str, ",");
+ g_string_append (str, node->errors[i]);
+ }
+ g_string_append (str, ">");
+ }
+ }
+}
+
+/* Types below somewhat augment a more basic type that has
+ * an entry in the direcory. An array type is an array of X.
+ * A list is a list of X.
+ */
+static void
+type_array_write (GIdlNode * node,
+ guint type_id, GIdlCompilerContext * ctx)
+{
+ GIdlNodeType *type = (GIdlNodeType *) node;
+
+ const gchar *array_struct =
+ " ArrayTypeBlob "ID_TO_ENTRY";\n";
+
+ const gchar *array_initialiser =
+ " {\n"
+ " {%d, 0, %d},\n"
+ " %d, %d, 0, %d,\n";
+
+ fprintf(ctx->mdata_struct, array_struct, type_id);
+
+ fprintf(ctx->mdata_init, array_initialiser,
+ 1,
+ type->tag,
+ type->zero_terminated,
+ type->has_length,
+ type->length);
+
+ g_idl_compiler_write_simple_type_blob ((GIdlNode*)type->parameter_type1, ctx);
+
+ fprintf(ctx->mdata_init, " },\n\n");
+}
+
+static void
+type_list_write (GIdlNode * node,
+ guint type_id,
+ GIdlCompilerContext * ctx)
+{
+ GIdlNodeType *type = (GIdlNodeType *) node;
+ guint n_types = 1;
+
+ const gchar *array_struct =
+ " struct {\n"
+ " ParamTypeBlob fixed;\n"
+ " SimpleTypeBlob type[%d];\n"
+ " } "ID_TO_ENTRY";\n";
+
+ const gchar *array_initialiser =
+ " {\n"
+ " {\n"
+ " {%d, 0, %d},\n"
+ " 0, %d,\n"
+ " },\n";
+
+ fprintf(ctx->mdata_struct, array_struct, n_types, type_id);
+
+ fprintf(ctx->mdata_init, array_initialiser,
+ 1,
+ type->tag,
+ n_types);
+
+ fprintf(ctx->mdata_init, " {\n");
+ if (type->parameter_type1)
+ {
+ g_idl_compiler_write_simple_type_blob ((GIdlNode*)type->parameter_type1, ctx);
+ }
+ fprintf(ctx->mdata_init, " },\n");
+
+ fprintf(ctx->mdata_init, " },\n\n");
+}
+
+static void
+type_hash_write (GIdlNode * node,
+ guint type_id, GIdlCompilerContext * ctx)
+{
+ GIdlNodeType *type = (GIdlNodeType *) node;
+ guint n_types = 2;
+
+ const gchar *hash_struct =
+ " struct {\n"
+ " ParamTypeBlob fixed;\n"
+ " SimpleTypeBlob type[%d];\n"
+ " } "ID_TO_ENTRY";\n";
+
+ const gchar *hash_initialiser =
+ " {\n"
+ " {\n"
+ " {%d, 0, %d},\n"
+ " 0, %d,\n"
+ " },\n";
+
+ fprintf(ctx->mdata_struct, hash_struct, n_types, type_id);
+
+ fprintf(ctx->mdata_init, hash_initialiser,
+ 1,
+ type->tag,
+ n_types);
+
+ fprintf(ctx->mdata_init, " {\n");
+ if (type->parameter_type1)
+ {
+ g_idl_compiler_write_simple_type_blob ((GIdlNode*)type->parameter_type1, ctx);
+ }
+ if (type->parameter_type2)
+ {
+ g_idl_compiler_write_simple_type_blob ((GIdlNode*)type->parameter_type2, ctx);
+ }
+ fprintf(ctx->mdata_init, " },\n");
+
+ fprintf(ctx->mdata_init, " },\n\n");
+}
+
+static void
+type_error_write (GIdlNode * node,
+ guint type_id, GIdlCompilerContext * ctx)
+{
+ GIdlNodeType *type = (GIdlNodeType *) node;
+ guint n_domains = 0;
+ guint i;
+
+ const gchar *error_struct =
+ " struct {\n"
+ " ErrorTypeBlob fixed;\n"
+ " guint16 domains[%d];\n"
+ " } "ID_TO_ENTRY";\n";
+
+ const gchar *error_initialiser =
+ " {\n"
+ " {\n"
+ " {%d, 0, %d},\n"
+ " %d,\n"
+ " },\n";
+
+ const gchar *error_domain_entry =
+ " %d,\n";
+
+ if (type->errors)
+ {
+ n_domains = g_strv_length(type->errors);
+ }
+
+ fprintf(ctx->mdata_struct, error_struct, n_domains, type_id);
+
+ fprintf(ctx->mdata_init, error_initialiser,
+ 1,
+ type->tag,
+ n_domains);
+
+ fprintf(ctx->mdata_init, " {\n");
+ for (i=0; i < n_domains; i++)
+ {
+ fprintf(ctx->mdata_init, error_domain_entry,
+ g_idl_compiler_get_entry_dirid (ctx, type->errors[i]));
+ }
+ fprintf(ctx->mdata_init, " },\n");
+
+ fprintf(ctx->mdata_init, " },\n\n");
+}
+
+static void
+type_complex_write (GIdlNode * node,
+ guint type_id, GIdlCompilerContext * ctx)
+{
+ GIdlNodeType *type = (GIdlNodeType *) node;
+
+ switch (type->tag)
+ {
+ case TYPE_TAG_ARRAY:
+ {
+ type_array_write (node, type_id, ctx);
+ }
+ break;
+
+ case TYPE_TAG_LIST:
+ case TYPE_TAG_SLIST:
+ {
+ type_list_write (node, type_id, ctx);
+ }
+ break;
+
+ case TYPE_TAG_HASH:
+ {
+ type_hash_write (node, type_id, ctx);
+ }
+ break;
+
+ case TYPE_TAG_ERROR:
+ {
+ type_error_write (node, type_id, ctx);
+ }
+ break;
+
+ default:
+ g_error ("Unknown type tag %d\n", type->tag);
+ break;
+ }
+}
+
+/* This is called at the end of any entries that may have
+ * added complex type blobs to the type list.
+ *
+ * These can only be written out to the metadata at the end of a previous
+ * entry and so are deffered until the entry is finished.
+ */
+void
+g_idl_compiler_write_deferred_type_blobs (GIdlCompilerContext *ctx)
+{
+ GIdlNodeType *type;
+ guint entry_id;
+ type = (GIdlNodeType *) g_idl_compiler_pop_deferred_type_node (ctx, &entry_id);
+
+ while (type)
+ {
+ fprintf(ctx->mdata_init, " /*Entry - %d*/\n",
+ entry_id);
+ type_complex_write ((GIdlNode *) type, entry_id, ctx);
+ type = (GIdlNodeType *) g_idl_compiler_pop_deferred_type_node (ctx, &entry_id);
+ }
+}
+
+/*
+ * This function writes out a simple type blob initializer.
+ * Simple type blobs are only included in other entries.
+ */
+void
+g_idl_compiler_write_simple_type_blob (GIdlNode * node, GIdlCompilerContext * ctx)
+{
+ GIdlNodeType *type = (GIdlNodeType *) node;
+
+ const gchar *simple_initialiser =
+ " {\n"
+ " {%d, 0, %d}, 0\n"
+ " },\n";
+ const gchar *symbol_initialiser =
+ " {\n"
+ " {%d, 0, %d}, %d,\n"
+ " },\n";
+ const gchar *complex_initialiser =
+ " {\n"
+ " {%d, 0, %d}, "TYPE_POINTER",\n"
+ " },\n";
+
+ /* If this is a simple type */
+ /* Simple types are not given their own entry
+ * into the global structure. They are a member of
+ * another entry.
+ */
+ if (TYPE_IS_SIMPLE(type->tag))
+ {
+ fprintf (ctx->mdata_init, simple_initialiser,
+ type->is_pointer, type->tag);
+ }
+ else if (TYPE_IS_SYMBOL(type->tag))
+ {
+ guint dir_id;
+
+ dir_id = g_idl_compiler_get_entry_dirid(ctx, type->interface);
+
+ fprintf (ctx->mdata_init, symbol_initialiser,
+ type->is_pointer, type->tag,
+ dir_id);
+ }
+ else
+ {
+ gpointer type_id;
+ GString *str;
+ gchar *s;
+
+ str = g_string_new (0);
+ g_idl_compiler_serialize_type (type, str);
+ s = g_string_free (str, FALSE);
+
+ type_id = g_hash_table_lookup (ctx->typesdb, s);
+ if (type_id)
+ {
+ g_free (s);
+ }
+ else
+ {
+ type_id = GINT_TO_POINTER (g_idl_compiler_get_unique_id ());
+ g_hash_table_insert (ctx->typesdb, s, type_id);
+ g_idl_compiler_push_deferred_type_node (ctx, node, GPOINTER_TO_INT(type_id));
+ }
+
+ fprintf (ctx->mdata_init, complex_initialiser,
+ type->is_pointer, type->tag,
+ ctx->struct_name, GPOINTER_TO_INT(type_id));
+ }
+}
Added: trunk/tools/gidlcompilertypenode.h
==============================================================================
--- (empty file)
+++ trunk/tools/gidlcompilertypenode.h Mon Mar 10 17:45:59 2008
@@ -0,0 +1,44 @@
+/* GObject introspection: Parsed IDL
+ *
+ * Copyright (C) 2008 Codethink Ltd
+ *
+ * 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_COMP_TYPE_N_H__
+#define __G_IDL_COMP_TYPE_N_H__
+
+#include <glib.h>
+
+#include "gidlnode.h"
+#include "gidlcompilercontext.h"
+
+G_BEGIN_DECLS
+
+const gchar *
+g_idl_compiler_name_basic_type(guint type_tag);
+
+void
+g_idl_compiler_serialize_type (GIdlNodeType * node, GString * str);
+
+void
+g_idl_compiler_write_deferred_type_blobs (GIdlCompilerContext *ctx);
+
+void
+g_idl_compiler_write_simple_type_blob (GIdlNode * node, GIdlCompilerContext * ctx);
+
+G_END_DECLS
+#endif /* __G_IDL_COMP_TYPE_N_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]