gobject-introspection r130 - in trunk: girepository tools



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]