/* GObject introspection: Typelib creation
*
* Copyright (C) 2005 Matthias Clasen
+ * Copyright (C) 2008,2009 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
g_message ("%lu types (%lu before sharing)", unique_types_count, types_count);
}
+#define DO_ALIGNED_COPY(dest_addr, value, type) \
+do { \
+ type tmp_var; \
+ tmp_var = value; \
+ memcpy(dest_addr, &tmp_var, sizeof(type)); \
+} while(0)
+
#define ALIGN_VALUE(this, boundary) \
(( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
}
node->type = type;
+ node->offset = 0;
+ node->attributes = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_free);
return node;
}
GIrNodeVFunc *vfunc = (GIrNodeVFunc *)node;
g_free (node->name);
+ g_free (vfunc->invoker);
for (l = vfunc->parameters; l; l = l->next)
g_ir_node_free ((GIrNode *)l->data);
g_list_free (vfunc->parameters);
g_free (node->name);
g_ir_node_free ((GIrNode *)field->type);
+ g_ir_node_free ((GIrNode *)field->callback);
}
break;
break;
}
+ g_hash_table_destroy (node->attributes);
+
g_free (node);
}
break;
case G_IR_NODE_FIELD:
- size = sizeof (FieldBlob);
+ {
+ GIrNodeField *field = (GIrNodeField *)node;
+
+ size = sizeof (FieldBlob);
+ if (field->callback)
+ size += g_ir_node_get_size ((GIrNode *)field->callback);
+ }
break;
case G_IR_NODE_CONSTANT:
return size;
}
+static void
+add_attribute_size (gpointer key, gpointer value, gpointer data)
+{
+ const gchar *key_str = key;
+ const gchar *value_str = value;
+ gint *size_p = data;
+
+ *size_p += sizeof (AttributeBlob);
+ *size_p += ALIGN_VALUE (strlen (key_str) + 1, 4);
+ *size_p += ALIGN_VALUE (strlen (value_str) + 1, 4);
+}
+
/* returns the full size of the blob including variable-size parts */
static guint32
g_ir_node_get_full_size_internal (GIrNode *parent,
size = sizeof (FieldBlob);
size += ALIGN_VALUE (strlen (node->name) + 1, 4);
- size += g_ir_node_get_full_size_internal (node, (GIrNode *)field->type);
+ if (field->callback)
+ size += g_ir_node_get_full_size_internal (node, (GIrNode *)field->callback);
+ else
+ size += g_ir_node_get_full_size_internal (node, (GIrNode *)field->type);
}
break;
return g_ir_node_get_full_size_internal (NULL, node);
}
+guint32
+g_ir_node_get_attribute_size (GIrNode *node)
+{
+ guint32 size = 0;
+ g_hash_table_foreach (node->attributes, add_attribute_size, &size);
+ return size;
+}
+
int
g_ir_node_cmp (GIrNode *node,
GIrNode *other)
goto out;
}
- g_warning ("Entry '%s' not found", name);
+ g_ir_module_fatal (module, 0, "Type reference '%s' not found", name);
out:
return node != NULL;
}
+static int
+get_index_of_member_type (GIrNodeInterface *node,
+ GIrNodeTypeId type,
+ const char *name)
+{
+ guint index = -1;
+ GList *l;
+
+ for (l = node->members; l; l = l->next)
+ {
+ GIrNode *node = l->data;
+
+ if (node->type != type)
+ continue;
+
+ index++;
+
+ if (strcmp (node->name, name) == 0)
+ break;
+ }
+
+ return index;
+}
+
static void
serialize_type (GIrModule *module,
GList *modules,
"uint32",
"int64",
"uint64",
+ "short",
+ "ushort",
"int",
"uint",
"long",
"size",
"float",
"double",
+ "time_t",
+ "GType",
"utf8",
"filename",
- "string",
- "sequence",
- "any"
};
if (node->tag < GI_TYPE_TAG_ARRAY)
g_ir_node_build_members (GList **members,
GIrNodeTypeId type,
guint16 *count,
+ GIrNode *parent,
GIrTypelibBuild *build,
guint32 *offset,
guint32 *offset2)
if (member->type == type)
{
(*count)++;
- g_ir_node_build_typelib (member, build, offset, offset2);
+ g_ir_node_build_typelib (member, parent, build, offset, offset2);
*members = g_list_delete_link (*members, l);
}
l = next;
void
g_ir_node_build_typelib (GIrNode *node,
+ GIrNode *parent,
GIrTypelibBuild *build,
guint32 *offset,
guint32 *offset2)
g_ir_node_compute_offsets (node, module, modules);
+ /* We should only be building each node once. If we do a typelib expansion, we also
+ * reset the offset in girmodule.c.
+ */
+ g_assert (node->offset == 0);
+ node->offset = *offset;
+ build->offset_ordered_nodes = g_list_prepend (build->offset_ordered_nodes, node);
+
+ build->n_attributes += g_hash_table_size (node->attributes);
+
switch (node->type)
{
case G_IR_NODE_TYPE:
type->tag == GI_TYPE_TAG_UTF8 ||
type->tag == GI_TYPE_TAG_FILENAME)
{
- blob->reserved = 0;
- blob->reserved2 = 0;
- blob->pointer = type->is_pointer;
- blob->reserved3 = 0;
- blob->tag = type->tag;
+ blob->flags.reserved = 0;
+ blob->flags.reserved2 = 0;
+ blob->flags.pointer = type->is_pointer;
+ blob->flags.reserved3 = 0;
+ blob->flags.tag = type->tag;
}
else
{
array->has_size = type->has_size;
array->reserved2 = 0;
if (array->has_length)
- array->length = type->length;
+ array->dimensions.length = type->length;
else if (array->has_size)
- array->size = type->size;
+ array->dimensions.size = type->size;
else
- array->length = -1;
+ array->dimensions.length = -1;
pos = *offset2 + G_STRUCT_OFFSET (ArrayTypeBlob, type);
*offset2 += sizeof (ArrayTypeBlob);
- g_ir_node_build_typelib ((GIrNode *)type->parameter_type1,
- build, &pos, offset2);
+ g_ir_node_build_typelib ((GIrNode *)type->parameter_type1,
+ node, build, &pos, offset2);
}
break;
*offset2 += sizeof (ParamTypeBlob) + sizeof (SimpleTypeBlob);
g_ir_node_build_typelib ((GIrNode *)type->parameter_type1,
- build, &pos, offset2);
+ node, build, &pos, offset2);
}
break;
*offset2 += sizeof (ParamTypeBlob) + sizeof (SimpleTypeBlob)*2;
g_ir_node_build_typelib ((GIrNode *)type->parameter_type1,
- build, &pos, offset2);
+ node, build, &pos, offset2);
g_ir_node_build_typelib ((GIrNode *)type->parameter_type2,
- build, &pos, offset2);
+ node, build, &pos, offset2);
}
break;
FieldBlob *blob;
blob = (FieldBlob *)&data[*offset];
- /* We handle the size member specially below, so subtract it */
- *offset += sizeof (FieldBlob) - sizeof (SimpleTypeBlob);
blob->name = write_string (node->name, strings, data, offset2);
blob->readable = field->readable;
else
blob->struct_offset = 0xFFFF; /* mark as unknown */
- g_ir_node_build_typelib ((GIrNode *)field->type,
- build, offset, offset2);
+ if (field->callback)
+ {
+ blob->has_embedded_type = TRUE;
+ blob->type.offset = GI_INFO_TYPE_CALLBACK;
+ *offset += sizeof (FieldBlob);
+ g_ir_node_build_typelib ((GIrNode *)field->callback,
+ node, build, offset, offset2);
+ }
+ else
+ {
+ blob->has_embedded_type = FALSE;
+ /* We handle the size member specially below, so subtract it */
+ *offset += sizeof (FieldBlob) - sizeof (SimpleTypeBlob);
+ g_ir_node_build_typelib ((GIrNode *)field->type,
+ node, build, offset, offset2);
+ }
}
break;
blob->reserved = 0;
g_ir_node_build_typelib ((GIrNode *)prop->type,
- build, offset, offset2);
+ node, build, offset, offset2);
}
break;
g_debug ("building function '%s'", function->symbol);
g_ir_node_build_typelib ((GIrNode *)function->result->type,
- build, &signature, offset2);
+ node, build, &signature, offset2);
blob2->may_return_null = function->result->allow_none;
blob2->caller_owns_return_value = function->result->transfer;
{
GIrNode *param = (GIrNode *)l->data;
- g_ir_node_build_typelib (param, build, &signature, offset2);
+ g_ir_node_build_typelib (param, node, build, &signature, offset2);
}
}
blob->signature = signature;
g_ir_node_build_typelib ((GIrNode *)function->result->type,
- build, &signature, offset2);
+ node, build, &signature, offset2);
blob2->may_return_null = function->result->allow_none;
blob2->caller_owns_return_value = function->result->transfer;
{
GIrNode *param = (GIrNode *)l->data;
- g_ir_node_build_typelib (param, build, &signature, offset2);
+ g_ir_node_build_typelib (param, node, build, &signature, offset2);
}
}
break;
blob->signature = signature;
g_ir_node_build_typelib ((GIrNode *)signal->result->type,
- build, &signature, offset2);
+ node, build, &signature, offset2);
blob2->may_return_null = signal->result->allow_none;
blob2->caller_owns_return_value = signal->result->transfer;
{
GIrNode *param = (GIrNode *)l->data;
- g_ir_node_build_typelib (param, build, &signature, offset2);
+ g_ir_node_build_typelib (param, node, build, &signature, offset2);
}
}
break;
blob->class_closure = 0; /* FIXME */
blob->reserved = 0;
+ if (vfunc->invoker)
+ {
+ int index = get_index_of_member_type ((GIrNodeInterface*)parent, G_IR_NODE_FUNCTION, vfunc->invoker);
+ if (index == -1)
+ {
+ g_error ("Unknown member function %s for vfunc %s", vfunc->invoker, node->name);
+ }
+ blob->invoker = (guint) index;
+ }
+ else
+ blob->invoker = 0x3ff; /* max of 10 bits */
+
blob->struct_offset = vfunc->offset;
blob->reserved2 = 0;
blob->signature = signature;
g_ir_node_build_typelib ((GIrNode *)vfunc->result->type,
- build, &signature, offset2);
+ node, build, &signature, offset2);
blob2->may_return_null = vfunc->result->allow_none;
blob2->caller_owns_return_value = vfunc->result->transfer;
{
GIrNode *param = (GIrNode *)l->data;
- g_ir_node_build_typelib (param, build, &signature, offset2);
+ g_ir_node_build_typelib (param, node, build, &signature, offset2);
}
}
break;
blob->closure = param->closure;
blob->destroy = param->destroy;
- g_ir_node_build_typelib ((GIrNode *)param->type, build, offset, offset2);
+ g_ir_node_build_typelib ((GIrNode *)param->type, node, build, offset, offset2);
}
break;
members = g_list_copy (struct_->members);
g_ir_node_build_members (&members, G_IR_NODE_FIELD, &blob->n_fields,
- build, offset, offset2);
+ node, build, offset, offset2);
g_ir_node_build_members (&members, G_IR_NODE_FUNCTION, &blob->n_methods,
- build, offset, offset2);
+ node, build, offset, offset2);
g_ir_node_check_unhandled_members (&members, node->type);
members = g_list_copy (boxed->members);
g_ir_node_build_members (&members, G_IR_NODE_FIELD, &blob->n_fields,
- build, offset, offset2);
+ node, build, offset, offset2);
g_ir_node_build_members (&members, G_IR_NODE_FUNCTION, &blob->n_methods,
- build, offset, offset2);
+ node, build, offset, offset2);
g_ir_node_check_unhandled_members (&members, node->type);
members = g_list_copy (union_->members);
g_ir_node_build_members (&members, G_IR_NODE_FIELD, &blob->n_fields,
- build, offset, offset2);
+ node, build, offset, offset2);
g_ir_node_build_members (&members, G_IR_NODE_FUNCTION, &blob->n_functions,
- build, offset, offset2);
+ node, build, offset, offset2);
g_ir_node_check_unhandled_members (&members, node->type);
{
GIrNode *member = (GIrNode *)l->data;
- g_ir_node_build_typelib (member, build, offset, offset2);
+ g_ir_node_build_typelib (member, node, build, offset, offset2);
}
}
}
GIrNode *value = (GIrNode *)l->data;
blob->n_values++;
- g_ir_node_build_typelib (value, build, offset, offset2);
+ g_ir_node_build_typelib (value, node, build, offset, offset2);
}
}
break;
*offset = ALIGN_VALUE (*offset, 4);
g_ir_node_build_members (&members, G_IR_NODE_FIELD, &blob->n_fields,
- build, offset, offset2);
+ node, build, offset, offset2);
*offset = ALIGN_VALUE (*offset, 4);
g_ir_node_build_members (&members, G_IR_NODE_PROPERTY, &blob->n_properties,
- build, offset, offset2);
+ node, build, offset, offset2);
*offset = ALIGN_VALUE (*offset, 4);
g_ir_node_build_members (&members, G_IR_NODE_FUNCTION, &blob->n_methods,
- build, offset, offset2);
+ node, build, offset, offset2);
*offset = ALIGN_VALUE (*offset, 4);
g_ir_node_build_members (&members, G_IR_NODE_SIGNAL, &blob->n_signals,
- build, offset, offset2);
+ node, build, offset, offset2);
*offset = ALIGN_VALUE (*offset, 4);
g_ir_node_build_members (&members, G_IR_NODE_VFUNC, &blob->n_vfuncs,
- build, offset, offset2);
+ node, build, offset, offset2);
*offset = ALIGN_VALUE (*offset, 4);
g_ir_node_build_members (&members, G_IR_NODE_CONSTANT, &blob->n_constants,
- build, offset, offset2);
+ node, build, offset, offset2);
g_ir_node_check_unhandled_members (&members, node->type);
*offset = ALIGN_VALUE (*offset, 4);
g_ir_node_build_members (&members, G_IR_NODE_PROPERTY, &blob->n_properties,
- build, offset, offset2);
+ node, build, offset, offset2);
*offset = ALIGN_VALUE (*offset, 4);
g_ir_node_build_members (&members, G_IR_NODE_FUNCTION, &blob->n_methods,
- build, offset, offset2);
+ node, build, offset, offset2);
*offset = ALIGN_VALUE (*offset, 4);
g_ir_node_build_members (&members, G_IR_NODE_SIGNAL, &blob->n_signals,
- build, offset, offset2);
+ node, build, offset, offset2);
*offset = ALIGN_VALUE (*offset, 4);
g_ir_node_build_members (&members, G_IR_NODE_VFUNC, &blob->n_vfuncs,
- build, offset, offset2);
+ node, build, offset, offset2);
*offset = ALIGN_VALUE (*offset, 4);
g_ir_node_build_members (&members, G_IR_NODE_CONSTANT, &blob->n_constants,
- build, offset, offset2);
+ node, build, offset, offset2);
g_ir_node_check_unhandled_members (&members, node->type);
break;
case GI_TYPE_TAG_INT64:
blob->size = 8;
- *(gint64*)&data[blob->offset] = (gint64) parse_int_value (constant->value);
+ DO_ALIGNED_COPY(&data[blob->offset], parse_int_value (constant->value), gint64);
break;
case GI_TYPE_TAG_UINT64:
blob->size = 8;
- *(guint64*)&data[blob->offset] = (guint64) parse_uint_value (constant->value);
+ DO_ALIGNED_COPY(&data[blob->offset], parse_uint_value (constant->value), guint64);
+ break;
+ case GI_TYPE_TAG_SHORT:
+ blob->size = sizeof (gshort);
+ *(gshort*)&data[blob->offset] = (gshort) parse_int_value (constant->value);
+ break;
+ case GI_TYPE_TAG_USHORT:
+ blob->size = sizeof (gushort);
+ *(gushort*)&data[blob->offset] = (gushort) parse_uint_value (constant->value);
break;
case GI_TYPE_TAG_INT:
blob->size = sizeof (gint);
case GI_TYPE_TAG_SSIZE: /* FIXME */
case GI_TYPE_TAG_LONG:
blob->size = sizeof (glong);
- *(glong*)&data[blob->offset] = (glong) parse_int_value (constant->value);
+ DO_ALIGNED_COPY(&data[blob->offset], parse_int_value (constant->value), glong);
break;
case GI_TYPE_TAG_SIZE: /* FIXME */
case GI_TYPE_TAG_TIME_T:
case GI_TYPE_TAG_ULONG:
blob->size = sizeof (gulong);
- *(gulong*)&data[blob->offset] = (gulong) parse_uint_value (constant->value);
+ DO_ALIGNED_COPY(&data[blob->offset], parse_uint_value (constant->value), gulong);
break;
case GI_TYPE_TAG_FLOAT:
blob->size = sizeof (gfloat);
- *(gfloat*)&data[blob->offset] = (gfloat) parse_float_value (constant->value);
+ DO_ALIGNED_COPY(&data[blob->offset], parse_float_value (constant->value), gfloat);
break;
case GI_TYPE_TAG_DOUBLE:
blob->size = sizeof (gdouble);
- *(gdouble*)&data[blob->offset] = (gdouble) parse_float_value (constant->value);
+ DO_ALIGNED_COPY(&data[blob->offset], parse_float_value (constant->value), gdouble);
break;
case GI_TYPE_TAG_UTF8:
case GI_TYPE_TAG_FILENAME:
}
*offset2 += ALIGN_VALUE (blob->size, 4);
- g_ir_node_build_typelib ((GIrNode *)constant->type, build, &pos, offset2);
+ g_ir_node_build_typelib ((GIrNode *)constant->type, node, build, &pos, offset2);
}
break;
default:
old_offset, *offset, old_offset2, *offset2);
if (*offset2 - old_offset2 + *offset - old_offset > g_ir_node_get_full_size (node))
- g_error ("exceeding space reservation !!");
+ g_error ("exceeding space reservation; offset: %d (prev %d) offset2: %d (prev %d) nodesize: %d",
+ *offset, old_offset, *offset2, old_offset2, g_ir_node_get_full_size (node));
}
/* if str is already in the pool, return previous location, otherwise write str