[girepository] Remove trailing whitespace
[gnome.gobject-introspection] / girepository / girmodule.c
index 5f5ae09..66efceb 100644 (file)
@@ -1,4 +1,4 @@
-/* GObject introspection: Typelib creation 
+/* GObject introspection: Typelib creation
  *
  * Copyright (C) 2005 Matthias Clasen
  *
@@ -20,6 +20,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include "girmodule.h"
 #include "girnode.h"
 
 
 GIrModule *
-g_ir_module_new (const gchar *name, 
+g_ir_module_new (const gchar *name,
                 const gchar *version,
-                const gchar *shared_library)
+                const gchar *shared_library,
+                const gchar *c_prefix)
 {
   GIrModule *module;
-  
+
   module = g_new0 (GIrModule, 1);
 
   module->name = g_strdup (name);
@@ -43,6 +45,7 @@ g_ir_module_new (const gchar *name,
       module->shared_library = g_strdup (shared_library);
   else
       module->shared_library = NULL;
+  module->c_prefix = g_strdup (c_prefix);
   module->dependencies = NULL;
   module->entries = NULL;
 
@@ -73,6 +76,39 @@ g_ir_module_free (GIrModule *module)
   g_free (module);
 }
 
+/**
+ * g_ir_module_fatal:
+ * @module: Current module
+ * @line: Origin line number, or 0 if unknown
+ * @msg: printf-format string
+ * @args: Remaining arguments
+ *
+ * Report a fatal error, then exit.
+ */
+void
+g_ir_module_fatal (GIrModule  *module,
+                   guint       line,
+                   const char *msg,
+                   ...)
+{
+  char *formatted;
+
+  va_list args;
+
+  va_start (args, msg);
+
+  formatted = g_strdup_vprintf (msg, args);
+
+  if (line)
+    g_printerr ("%s-%s.gir:%d: error: %s\n", module->name, module->version, line, formatted);
+  else
+    g_printerr ("%s-%s.gir: error: %s\n", module->name, module->version, formatted);
+
+  exit (1);
+
+  va_end (args);
+}
+
 static void
 add_alias_foreach (gpointer key,
                   gpointer value,
@@ -109,6 +145,53 @@ g_ir_module_add_include_module (GIrModule  *module,
                        module);
 }
 
+struct AttributeWriteData
+{
+  guint count;
+  guchar *databuf;
+  GIrNode *node;
+  GHashTable *strings;
+  guint32 *offset;
+  guint32 *offset2;
+};
+
+static void
+write_attribute (gpointer key, gpointer value, gpointer datap)
+{
+  struct AttributeWriteData *data = datap;
+  guint32 old_offset = *(data->offset);
+  AttributeBlob *blob = (AttributeBlob*)&(data->databuf[old_offset]);
+
+  *(data->offset) += sizeof (AttributeBlob);
+
+  blob->offset = data->node->offset;
+  blob->name = write_string ((const char*) key, data->strings, data->databuf, data->offset2);
+  blob->value = write_string ((const char*) value, data->strings, data->databuf, data->offset2);
+
+  data->count++;
+}
+
+static guint
+write_attributes (GIrModule *module,
+                   GIrNode   *node,
+                   GHashTable *strings,
+                   guchar    *data,
+                   guint32   *offset,
+                   guint32   *offset2)
+{
+  struct AttributeWriteData wdata;
+  wdata.count = 0;
+  wdata.databuf = data;
+  wdata.node = node;
+  wdata.offset = offset;
+  wdata.offset2 = offset2;
+  wdata.strings = strings;
+
+  g_hash_table_foreach (node->attributes, write_attribute, &wdata);
+
+  return wdata.count;
+}
+
 GTypelib *
 g_ir_module_build_typelib (GIrModule  *module,
                             GList       *modules)
@@ -126,6 +209,7 @@ g_ir_module_build_typelib (GIrModule  *module,
   guint32 size, offset, offset2, old_offset;
   GHashTable *strings;
   GHashTable *types;
+  GList *offset_ordered_nodes;
   char *dependencies;
   guchar *data;
 
@@ -158,11 +242,12 @@ g_ir_module_build_typelib (GIrModule  *module,
   _g_irnode_init_stats ();
   strings = g_hash_table_new (g_str_hash, g_str_equal);
   types = g_hash_table_new (g_str_hash, g_str_equal);
+  offset_ordered_nodes = NULL;
   n_entries = g_list_length (module->entries);
 
   g_message ("%d entries (%d local), %d dependencies\n", n_entries, n_local_entries,
             g_list_length (module->dependencies));
-  
+
   dir_size = n_entries * sizeof (DirEntry);
   size = header_size + dir_size;
 
@@ -171,18 +256,24 @@ g_ir_module_build_typelib (GIrModule  *module,
   for (e = module->entries; e; e = e->next)
     {
       GIrNode *node = e->data;
-      
+
       size += g_ir_node_get_full_size (node);
+      size += g_ir_node_get_attribute_size (node);
+
+      /* Also reset the offset here */
+      node->offset = 0;
     }
 
   /* Adjust size for strings allocated in header below specially */
-  size += strlen (module->name);
-  if (module->shared_library) 
-    size += strlen (module->shared_library);
+  size += ALIGN_VALUE (strlen (module->name) + 1, 4);
+  if (module->shared_library)
+    size += ALIGN_VALUE (strlen (module->shared_library) + 1, 4);
   if (dependencies != NULL)
-    size += strlen (dependencies);
+    size += ALIGN_VALUE (strlen (dependencies) + 1, 4);
+  if (module->c_prefix != NULL)
+    size += ALIGN_VALUE (strlen (module->c_prefix) + 1, 4);
 
-  g_message ("allocating %d bytes (%d header, %d directory, %d entries)\n", 
+  g_message ("allocating %d bytes (%d header, %d directory, %d entries)\n",
          size, header_size, dir_size, size - header_size - dir_size);
 
   data = g_malloc0 (size);
@@ -195,8 +286,11 @@ g_ir_module_build_typelib (GIrModule  *module,
   header->reserved = 0;
   header->n_entries = n_entries;
   header->n_local_entries = n_local_entries;
-  header->n_annotations = 0;
-  header->annotations = 0; /* filled in later */
+  header->n_attributes = 0;
+  header->attributes = 0; /* filled in later */
+  /* NOTE: When writing strings to the typelib here, you should also update
+   * the size calculations above.
+   */
   if (dependencies != NULL)
     header->dependencies = write_string (dependencies, strings, data, &header_size);
   else
@@ -207,6 +301,10 @@ g_ir_module_build_typelib (GIrModule  *module,
   header->shared_library = (module->shared_library?
                              write_string (module->shared_library, strings, data, &header_size)
                              : 0);
+  if (module->c_prefix != NULL)
+    header->c_prefix = write_string (module->c_prefix, strings, data, &header_size);
+  else
+    header->c_prefix = 0;
   header->directory = ALIGN_VALUE (header_size, 4);
   header->entry_blob_size = sizeof (DirEntry);
   header->function_blob_size = sizeof (FunctionBlob);
@@ -219,7 +317,7 @@ g_ir_module_build_typelib (GIrModule  *module,
   header->value_blob_size = sizeof (ValueBlob);
   header->constant_blob_size = sizeof (ConstantBlob);
   header->error_domain_blob_size = sizeof (ErrorDomainBlob);
-  header->annotation_blob_size = sizeof (AnnotationBlob);
+  header->attribute_blob_size = sizeof (AttributeBlob);
   header->signature_blob_size = sizeof (SignatureBlob);
   header->enum_blob_size = sizeof (EnumBlob);
   header->struct_blob_size = sizeof (StructBlob);
@@ -234,6 +332,7 @@ g_ir_module_build_typelib (GIrModule  *module,
 
   for (e = module->entries, i = 0; e; e = e->next, i++)
     {
+      GIrTypelibBuild build;
       GIrNode *node = e->data;
 
       if (strchr (node->name, '.'))
@@ -244,10 +343,17 @@ g_ir_module_build_typelib (GIrModule  *module,
       /* we picked up implicit xref nodes, start over */
       if (i == n_entries)
        {
+         GList *link;
          g_message ("Found implicit cross references, starting over");
 
          g_hash_table_destroy (strings);
          g_hash_table_destroy (types);
+
+         /* Reset the cached offsets */
+         for (link = offset_ordered_nodes; link; link = link->next)
+           ((GIrNode *) link->data)->offset = 0;
+
+         g_list_free (offset_ordered_nodes);
          strings = NULL;
 
          g_free (data);
@@ -255,13 +361,13 @@ g_ir_module_build_typelib (GIrModule  *module,
 
          goto restart;
        }
-       
+
       offset = offset2;
 
       if (node->type == G_IR_NODE_XREF)
        {
          const char *namespace = ((GIrNodeXRef*)node)->namespace;
-         
+
          entry->blob_type = 0;
          entry->local = FALSE;
          entry->offset = write_string (namespace, strings, data, &offset2);
@@ -277,8 +383,17 @@ g_ir_module_build_typelib (GIrModule  *module,
          entry->offset = offset;
          entry->name = write_string (node->name, strings, data, &offset2);
 
-         g_ir_node_build_typelib (node, module, modules, 
-                                    strings, types, data, &offset, &offset2);
+         build.module = module;
+         build.modules = modules;
+         build.strings = strings;
+         build.types = types;
+         build.offset_ordered_nodes = offset_ordered_nodes;
+         build.n_attributes = header->n_attributes;
+         build.data = data;
+         g_ir_node_build_typelib (node, NULL, &build, &offset, &offset2);
+
+         offset_ordered_nodes = build.offset_ordered_nodes;
+         header->n_attributes = build.n_attributes;
 
          if (offset2 > old_offset + g_ir_node_get_full_size (node))
            g_error ("left a hole of %d bytes\n", offset2 - old_offset - g_ir_node_get_full_size (node));
@@ -287,10 +402,24 @@ g_ir_module_build_typelib (GIrModule  *module,
       entry++;
     }
 
+  offset_ordered_nodes = g_list_reverse (offset_ordered_nodes);
+
+  g_message ("header: %d entries, %d attributes", header->n_entries, header->n_attributes);
+
   _g_irnode_dump_stats ();
 
-  header->annotations = offset2;
-  
+  /* Write attributes after the blobs */
+  offset = offset2;
+  header->attributes = offset;
+  offset2 = offset + header->n_attributes * header->attribute_blob_size;
+
+  for (e = offset_ordered_nodes; e; e = e->next)
+    {
+      GIrNode *node = e->data;
+
+      write_attributes (module, node, strings, data, &offset, &offset2);
+    }
+
   g_message ("reallocating to %d bytes", offset2);
 
   data = g_realloc (data, offset2);
@@ -300,6 +429,7 @@ g_ir_module_build_typelib (GIrModule  *module,
 
   g_hash_table_destroy (strings);
   g_hash_table_destroy (types);
+  g_list_free (offset_ordered_nodes);
 
   return typelib;
 }