-/* GObject introspection: Typelib creation
+/* GObject introspection: Typelib creation
*
* Copyright (C) 2005 Matthias Clasen
*
#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);
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;
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,
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)
guint32 size, offset, offset2, old_offset;
GHashTable *strings;
GHashTable *types;
+ GList *offset_ordered_nodes;
char *dependencies;
guchar *data;
_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;
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);
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
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);
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);
for (e = module->entries, i = 0; e; e = e->next, i++)
{
+ GIrTypelibBuild build;
GIrNode *node = e->data;
if (strchr (node->name, '.'))
/* 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);
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);
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));
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);
g_hash_table_destroy (strings);
g_hash_table_destroy (types);
+ g_list_free (offset_ordered_nodes);
return typelib;
}