gobject-introspection r288 - in trunk: . girepository tools
- From: pvanhoof svn gnome org
- To: svn-commits-list gnome org
- Subject: gobject-introspection r288 - in trunk: . girepository tools
- Date: Sun, 8 Jun 2008 14:37:30 +0000 (UTC)
Author: pvanhoof
Date: Sun Jun 8 14:37:30 2008
New Revision: 288
URL: http://svn.gnome.org/viewvc/gobject-introspection?rev=288&view=rev
Log:
2008-06-08 Philip Van Hoof <pvanhoof gnome org>
* girepository/girepository.c:
* girepository/gtypelib.c:
* girepository/ginfo.c:
* girepository/ginvoke.c:
* girepository/girepository.h:
* girepository/gtypelib.h:
* girepository/gmetadata.c:
* girepository/Makefile.am:
* girepository/gmetadata.h:
* tools/compiler.c:
* tools/gidlmodule.c:
* tools/gidlnode.c
* tools/generate.c:
* tools/gidlmodule.h:
* tools/gidlparser.c:
Renamed GMetadata to GTypelib
Added:
trunk/girepository/gtypelib.c
trunk/girepository/gtypelib.h
Removed:
trunk/girepository/gmetadata.c
trunk/girepository/gmetadata.h
Modified:
trunk/ChangeLog
trunk/girepository/Makefile.am
trunk/girepository/ginfo.c
trunk/girepository/ginvoke.c
trunk/girepository/girepository.c
trunk/girepository/girepository.h
trunk/tools/compiler.c
trunk/tools/generate.c
trunk/tools/gidlmodule.c
trunk/tools/gidlmodule.h
trunk/tools/gidlnode.c
trunk/tools/gidlparser.c
Modified: trunk/girepository/Makefile.am
==============================================================================
--- trunk/girepository/Makefile.am (original)
+++ trunk/girepository/Makefile.am Sun Jun 8 14:37:30 2008
@@ -8,8 +8,8 @@
libgirepository_la_SOURCES = \
girepository.c \
- gmetadata.h \
- gmetadata.c \
+ gtypelib.h \
+ gtypelib.c \
ginfo.c \
ginvoke.c
libgirepository_la_CPPFLAGS = $(GIREPO_CFLAGS)
Modified: trunk/girepository/ginfo.c
==============================================================================
--- trunk/girepository/ginfo.c (original)
+++ trunk/girepository/ginfo.c Sun Jun 8 14:37:30 2008
@@ -24,7 +24,7 @@
#include <glib-object.h>
#include "girepository.h"
-#include "gmetadata.h"
+#include "gtypelib.h"
struct _GIBaseInfo
{
@@ -32,7 +32,7 @@
gint ref_count;
GIBaseInfo *container;
- GMetadata *metadata;
+ GTypelib *metadata;
guint32 offset;
};
@@ -136,7 +136,7 @@
GIBaseInfo *
g_info_new (GIInfoType type,
GIBaseInfo *container,
- GMetadata *metadata,
+ GTypelib *metadata,
guint32 offset)
{
GIBaseInfo *info;
@@ -156,18 +156,18 @@
}
static GIBaseInfo *
-g_info_from_entry (GMetadata *metadata,
+g_info_from_entry (GTypelib *metadata,
guint16 index)
{
GIBaseInfo *result;
- DirEntry *entry = g_metadata_get_dir_entry (metadata, index);
+ DirEntry *entry = g_typelib_get_dir_entry (metadata, index);
if (entry->local)
result = g_info_new (entry->blob_type, NULL, metadata, entry->offset);
else
{
- const gchar *namespace = g_metadata_get_string (metadata, entry->offset);
- const gchar *name = g_metadata_get_string (metadata, entry->name);
+ const gchar *namespace = g_typelib_get_string (metadata, entry->offset);
+ const gchar *name = g_typelib_get_string (metadata, entry->name);
GIRepository *repository = g_irepository_get_default ();
@@ -240,7 +240,7 @@
{
CommonBlob *blob = (CommonBlob *)&info->metadata->data[info->offset];
- return g_metadata_get_string (info->metadata, blob->name);
+ return g_typelib_get_string (info->metadata, blob->name);
}
break;
@@ -248,7 +248,7 @@
{
ValueBlob *blob = (ValueBlob *)&info->metadata->data[info->offset];
- return g_metadata_get_string (info->metadata, blob->name);
+ return g_typelib_get_string (info->metadata, blob->name);
}
break;
@@ -256,7 +256,7 @@
{
SignalBlob *blob = (SignalBlob *)&info->metadata->data[info->offset];
- return g_metadata_get_string (info->metadata, blob->name);
+ return g_typelib_get_string (info->metadata, blob->name);
}
break;
@@ -264,7 +264,7 @@
{
PropertyBlob *blob = (PropertyBlob *)&info->metadata->data[info->offset];
- return g_metadata_get_string (info->metadata, blob->name);
+ return g_typelib_get_string (info->metadata, blob->name);
}
break;
@@ -272,7 +272,7 @@
{
VFuncBlob *blob = (VFuncBlob *)&info->metadata->data[info->offset];
- return g_metadata_get_string (info->metadata, blob->name);
+ return g_typelib_get_string (info->metadata, blob->name);
}
break;
@@ -280,7 +280,7 @@
{
FieldBlob *blob = (FieldBlob *)&info->metadata->data[info->offset];
- return g_metadata_get_string (info->metadata, blob->name);
+ return g_typelib_get_string (info->metadata, blob->name);
}
break;
@@ -288,7 +288,7 @@
{
ArgBlob *blob = (ArgBlob *)&info->metadata->data[info->offset];
- return g_metadata_get_string (info->metadata, blob->name);
+ return g_typelib_get_string (info->metadata, blob->name);
}
break;
@@ -320,7 +320,7 @@
return unresolved->namespace;
}
- return g_metadata_get_string (info->metadata, header->namespace);
+ return g_typelib_get_string (info->metadata, header->namespace);
}
gboolean
@@ -430,9 +430,9 @@
{
res = next;
- rname = g_metadata_get_string (base->metadata, res->name);
+ rname = g_typelib_get_string (base->metadata, res->name);
if (strcmp (name, rname) == 0)
- return g_metadata_get_string (base->metadata, res->value);
+ return g_typelib_get_string (base->metadata, res->value);
next = res += header->annotation_blob_size;
}
@@ -447,7 +447,7 @@
return info->container;
}
-GMetadata *
+GTypelib *
g_base_info_get_metadata (GIBaseInfo *info)
{
return info->metadata;
@@ -460,7 +460,7 @@
GIBaseInfo *base = (GIBaseInfo *)info;
FunctionBlob *blob = (FunctionBlob *)&base->metadata->data[base->offset];
- return g_metadata_get_string (base->metadata, blob->symbol);
+ return g_typelib_get_string (base->metadata, blob->symbol);
}
GIFunctionInfoFlags
@@ -530,7 +530,7 @@
GITypeInfo *
g_type_info_new (GIBaseInfo *container,
- GMetadata *metadata,
+ GTypelib *metadata,
guint32 offset)
{
SimpleTypeBlob *type = (SimpleTypeBlob *)&metadata->data[offset];
@@ -874,7 +874,7 @@
GIBaseInfo *base = (GIBaseInfo *)info;
ErrorDomainBlob *blob = (ErrorDomainBlob *)&base->metadata->data[base->offset];
- return g_metadata_get_string (base->metadata, blob->get_quark);
+ return g_typelib_get_string (base->metadata, blob->get_quark);
}
GIInterfaceInfo *
@@ -951,7 +951,7 @@
RegisteredTypeBlob *blob = (RegisteredTypeBlob *)&base->metadata->data[base->offset];
if (blob->gtype_name)
- return g_metadata_get_string (base->metadata, blob->gtype_name);
+ return g_typelib_get_string (base->metadata, blob->gtype_name);
return NULL;
}
@@ -963,7 +963,7 @@
RegisteredTypeBlob *blob = (RegisteredTypeBlob *)&base->metadata->data[base->offset];
if (blob->gtype_init)
- return g_metadata_get_string (base->metadata, blob->gtype_init);
+ return g_typelib_get_string (base->metadata, blob->gtype_init);
return NULL;
}
@@ -1116,7 +1116,7 @@
GIBaseInfo *base = (GIBaseInfo *)info;
ObjectBlob *blob = (ObjectBlob *)&base->metadata->data[base->offset];
- return g_metadata_get_string (base->metadata, blob->gtype_name);
+ return g_typelib_get_string (base->metadata, blob->gtype_name);
}
const gchar *
@@ -1125,7 +1125,7 @@
GIBaseInfo *base = (GIBaseInfo *)info;
ObjectBlob *blob = (ObjectBlob *)&base->metadata->data[base->offset];
- return g_metadata_get_string (base->metadata, blob->gtype_init);
+ return g_typelib_get_string (base->metadata, blob->gtype_init);
}
gint
Modified: trunk/girepository/ginvoke.c
==============================================================================
--- trunk/girepository/ginvoke.c (original)
+++ trunk/girepository/ginvoke.c Sun Jun 8 14:37:30 2008
@@ -24,7 +24,7 @@
#include <glib-object.h>
#include "girepository.h"
-#include "gmetadata.h"
+#include "gtypelib.h"
#include "config.h"
GQuark
Modified: trunk/girepository/girepository.c
==============================================================================
--- trunk/girepository/girepository.c (original)
+++ trunk/girepository/girepository.c Sun Jun 8 14:37:30 2008
@@ -26,7 +26,7 @@
#include <glib/gprintf.h>
#include <gmodule.h>
#include "girepository.h"
-#include "gmetadata.h"
+#include "gtypelib.h"
static GIRepository *default_repository = NULL;
static GHashTable *default_metadata = NULL;
@@ -34,7 +34,7 @@
struct _GIRepositoryPrivate
{
- GHashTable *metadata; /* (string) namespace -> GMetadata */
+ GHashTable *metadata; /* (string) namespace -> GTypelib */
};
G_DEFINE_TYPE (GIRepository, g_irepository, G_TYPE_OBJECT);
@@ -70,7 +70,7 @@
const gchar *
g_irepository_register (GIRepository *repository,
- GMetadata *metadata)
+ GTypelib *metadata)
{
Header *header;
const gchar *name;
@@ -88,7 +88,7 @@
if (repository->priv->metadata == NULL)
repository->priv->metadata = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) NULL,
- (GDestroyNotify) g_metadata_free);
+ (GDestroyNotify) g_typelib_free);
table = repository->priv->metadata;
}
else
@@ -96,11 +96,11 @@
if (default_metadata == NULL)
default_metadata = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) NULL,
- (GDestroyNotify) g_metadata_free);
+ (GDestroyNotify) g_typelib_free);
table = default_metadata;
}
- name = g_metadata_get_string (metadata, header->namespace);
+ name = g_typelib_get_string (metadata, header->namespace);
if (g_hash_table_lookup (table, name))
{
@@ -158,7 +158,7 @@
if (default_metadata == NULL)
default_metadata = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) NULL,
- (GDestroyNotify) g_metadata_free);
+ (GDestroyNotify) g_typelib_free);
default_repository->priv->metadata = default_metadata;
}
@@ -170,7 +170,7 @@
gpointer value,
gpointer data)
{
- guchar *metadata = ((GMetadata *) value)->data;
+ guchar *metadata = ((GTypelib *) value)->data;
gint *n_interfaces = (gint *)data;
*n_interfaces += ((Header *)metadata)->n_local_entries;
@@ -184,7 +184,7 @@
if (namespace)
{
- GMetadata *metadata;
+ GTypelib *metadata;
metadata = g_hash_table_lookup (repository->priv->metadata, namespace);
@@ -214,7 +214,7 @@
gpointer data)
{
gint i;
- GMetadata *metadata = (GMetadata *)value;
+ GTypelib *metadata = (GTypelib *)value;
IfaceData *iface_data = (IfaceData *)data;
gint index;
gint n_entries;
@@ -230,8 +230,8 @@
{
for (i = 1; i <= n_entries; i++)
{
- entry = g_metadata_get_dir_entry (metadata, i);
- name = g_metadata_get_string (metadata, entry->name);
+ entry = g_typelib_get_dir_entry (metadata, i);
+ name = g_typelib_get_string (metadata, entry->name);
if (strcmp (name, iface_data->name) == 0)
{
index = i;
@@ -243,12 +243,12 @@
{
for (i = 1; i <= n_entries; i++)
{
- entry = g_metadata_get_dir_entry (metadata, i);
+ entry = g_typelib_get_dir_entry (metadata, i);
if (entry->blob_type < 4)
continue;
offset = *(guint32*)&metadata->data[entry->offset + 8];
- type = g_metadata_get_string (metadata, offset);
+ type = g_typelib_get_string (metadata, offset);
if (strcmp (type, iface_data->type) == 0)
{
index = i;
@@ -266,7 +266,7 @@
if (index != 0)
{
- entry = g_metadata_get_dir_entry (metadata, index);
+ entry = g_typelib_get_dir_entry (metadata, index);
iface_data->iface = g_info_new (entry->blob_type, NULL,
metadata, entry->offset);
}
@@ -286,7 +286,7 @@
if (namespace)
{
- GMetadata *metadata;
+ GTypelib *metadata;
metadata = g_hash_table_lookup (repository->priv->metadata, namespace);
@@ -329,7 +329,7 @@
if (namespace)
{
- GMetadata *metadata;
+ GTypelib *metadata;
metadata = g_hash_table_lookup (repository->priv->metadata, namespace);
@@ -374,7 +374,7 @@
g_irepository_get_shared_library (GIRepository *repository,
const gchar *namespace)
{
- GMetadata *metadata;
+ GTypelib *metadata;
Header *header;
metadata = g_hash_table_lookup (repository->priv->metadata, namespace);
@@ -382,7 +382,7 @@
return NULL;
header = (Header *) metadata->data;
if (header->shared_library)
- return g_metadata_get_string (metadata, header->shared_library);
+ return g_typelib_get_string (metadata, header->shared_library);
else
return NULL;
}
@@ -418,7 +418,7 @@
gchar *fname, *full_path;
GMappedFile *mfile;
GError *error1 = NULL;
- GMetadata *metadata = NULL;
+ GTypelib *metadata = NULL;
const gchar *metadata_namespace, *shlib_fname;
GModule *module;
guint32 shlib;
@@ -449,8 +449,8 @@
continue;
}
g_free (full_path);
- metadata = g_metadata_new_from_mapped_file (mfile);
- metadata_namespace = g_metadata_get_string (metadata, ((Header *) metadata->data)->namespace);
+ metadata = g_typelib_new_from_mapped_file (mfile);
+ metadata_namespace = g_typelib_get_string (metadata, ((Header *) metadata->data)->namespace);
if (strcmp (metadata_namespace, namespace) != 0) {
g_set_error (error, G_IREPOSITORY_ERROR,
G_IREPOSITORY_ERROR_NAMESPACE_MISMATCH,
@@ -472,7 +472,7 @@
/* optionally load shared library and attach it to the metadata */
shlib = ((Header *) metadata->data)->shared_library;
if (shlib) {
- shlib_fname = g_metadata_get_string (metadata, shlib);
+ shlib_fname = g_typelib_get_string (metadata, shlib);
module = g_module_open (shlib_fname, G_MODULE_BIND_LAZY|G_MODULE_BIND_LOCAL);
if (module == NULL) {
g_set_error (error, G_IREPOSITORY_ERROR,
Modified: trunk/girepository/girepository.h
==============================================================================
--- trunk/girepository/girepository.h (original)
+++ trunk/girepository/girepository.h Sun Jun 8 14:37:30 2008
@@ -52,7 +52,7 @@
typedef struct _GITypeInfo GITypeInfo;
typedef struct _GIErrorDomainInfo GIErrorDomainInfo;
typedef struct _GIUnresolvedInfo GIUnresolvedInfo;
-typedef struct _GMetadata GMetadata;
+typedef struct _GTypelib GTypelib;
struct _GIRepository
{
@@ -73,7 +73,7 @@
GType g_irepository_get_type (void) G_GNUC_CONST;
GIRepository *g_irepository_get_default (void);
const gchar * g_irepository_register (GIRepository *repository,
- GMetadata *metadata);
+ GTypelib *metadata);
void g_irepository_unregister (GIRepository *repository,
const gchar *namespace);
const gchar * g_irepository_register_file (GIRepository *repository,
@@ -96,15 +96,15 @@
const gchar *namespace);
/* Metadata */
-GMetadata * g_metadata_new_from_memory (guchar *memory,
+GTypelib * g_typelib_new_from_memory (guchar *memory,
gsize len);
-GMetadata * g_metadata_new_from_const_memory (const guchar *memory,
+GTypelib * g_typelib_new_from_const_memory (const guchar *memory,
gsize len);
-GMetadata * g_metadata_new_from_mapped_file (GMappedFile *mfile);
-void g_metadata_free (GMetadata *metadata);
-void g_metadata_set_module (GMetadata *metadata,
+GTypelib * g_typelib_new_from_mapped_file (GMappedFile *mfile);
+void g_typelib_free (GTypelib *metadata);
+void g_typelib_set_module (GTypelib *metadata,
GModule *module);
-const gchar * g_metadata_get_namespace (GMetadata *metadata);
+const gchar * g_typelib_get_namespace (GTypelib *metadata);
typedef enum
{
@@ -156,11 +156,11 @@
const gchar * g_base_info_get_annotation (GIBaseInfo *info,
const gchar *name);
GIBaseInfo * g_base_info_get_container (GIBaseInfo *info);
-GMetadata * g_base_info_get_metadata (GIBaseInfo *info);
+GTypelib * g_base_info_get_metadata (GIBaseInfo *info);
GIBaseInfo * g_info_new (GIInfoType type,
GIBaseInfo *container,
- GMetadata *metadata,
+ GTypelib *metadata,
guint32 offset);
Added: trunk/girepository/gtypelib.c
==============================================================================
--- (empty file)
+++ trunk/girepository/gtypelib.c Sun Jun 8 14:37:30 2008
@@ -0,0 +1,1959 @@
+/* GObject introspection: metadata validation, auxiliary functions
+ * related to the binary metadata format
+ *
+ * Copyright (C) 2005 Matthias Clasen
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include "gtypelib.h"
+
+
+#define ALIGN_VALUE(this, boundary) \
+ (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
+
+
+DirEntry *
+g_typelib_get_dir_entry (GTypelib *metadata,
+ guint16 index)
+{
+ Header *header = (Header *)metadata->data;
+
+ return (DirEntry *)&metadata->data[header->directory + (index - 1) * header->entry_blob_size];
+}
+
+void
+g_typelib_check_sanity (void)
+{
+ /* Check that struct layout is as we expect */
+ g_assert (sizeof (Header) == 100);
+ g_assert (sizeof (DirEntry) == 12);
+ g_assert (sizeof (SimpleTypeBlob) == 4);
+ g_assert (sizeof (ArgBlob) == 12);
+ g_assert (sizeof (SignatureBlob) == 8);
+ g_assert (sizeof (CommonBlob) == 8);
+ g_assert (sizeof (FunctionBlob) == 16);
+ g_assert (sizeof (InterfaceTypeBlob) == 4);
+ g_assert (sizeof (ArrayTypeBlob) == 8);
+ g_assert (sizeof (ParamTypeBlob) == 4);
+ g_assert (sizeof (ErrorTypeBlob) == 4);
+ g_assert (sizeof (ErrorDomainBlob) == 16);
+ g_assert (sizeof (ValueBlob) == 12);
+ g_assert (sizeof (FieldBlob) == 12);
+ g_assert (sizeof (RegisteredTypeBlob) == 16);
+ g_assert (sizeof (StructBlob) == 20);
+ g_assert (sizeof (EnumBlob) == 20);
+ g_assert (sizeof (PropertyBlob) == 12);
+ g_assert (sizeof (SignalBlob) == 12);
+ g_assert (sizeof (VFuncBlob) == 16);
+ g_assert (sizeof (ObjectBlob) == 32);
+ g_assert (sizeof (InterfaceBlob) == 28);
+ g_assert (sizeof (ConstantBlob) == 20);
+ g_assert (sizeof (AnnotationBlob) == 12);
+ g_assert (sizeof (UnionBlob) == 28);
+}
+
+
+static gboolean
+is_aligned (guint32 offset)
+{
+ return offset == ALIGN_VALUE (offset, 4);
+}
+
+#define MAX_NAME_LEN 200
+
+static gboolean
+is_name (const guchar *data, guint32 offset)
+{
+ gchar *name;
+
+ name = (gchar*)&data[offset];
+
+ if (!memchr (name, '\0', MAX_NAME_LEN))
+ return FALSE;
+
+ if (strspn (name, G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "-_") < strlen (name))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_header (GTypelib *metadata,
+ GError **error)
+{
+ Header *header;
+
+ if (metadata->len < sizeof (Header))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ header = (Header *)metadata->data;
+
+ if (strncmp (header->magic, G_IDL_MAGIC, 16) != 0)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_HEADER,
+ "Magic string not found");
+ return FALSE;
+
+ }
+
+ if (header->major_version != 1 || header->minor_version != 0)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_HEADER,
+ "Version mismatch");
+ return FALSE;
+
+ }
+
+ if (header->n_entries < header->n_local_entries)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_HEADER,
+ "Inconsistent entry counts");
+ return FALSE;
+ }
+
+ if (header->size != metadata->len)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_HEADER,
+ "Metadata size mismatch");
+ return FALSE;
+ }
+
+ if (header->entry_blob_size != 12 ||
+ header->function_blob_size != 16 ||
+ header->callback_blob_size != 12 ||
+ header->signal_blob_size != 12 ||
+ header->vfunc_blob_size != 16 ||
+ header->arg_blob_size != 12 ||
+ header->property_blob_size != 12 ||
+ header->field_blob_size != 12 ||
+ header->value_blob_size != 12 ||
+ header->constant_blob_size != 20 ||
+ header->error_domain_blob_size != 16 ||
+ header->annotation_blob_size != 12 ||
+ header->signature_blob_size != 8 ||
+ header->enum_blob_size != 20 ||
+ header->struct_blob_size != 20 ||
+ header->object_blob_size != 32 ||
+ header->interface_blob_size != 28 ||
+ header->union_blob_size != 28)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_HEADER,
+ "Blob size mismatch");
+ return FALSE;
+ }
+
+ if (!is_aligned (header->directory))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_HEADER,
+ "Misaligned directory");
+ return FALSE;
+ }
+
+ if (!is_aligned (header->annotations))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_HEADER,
+ "Misaligned annotations");
+ return FALSE;
+ }
+
+ if (header->annotations == 0 && header->n_annotations > 0)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_HEADER,
+ "Wrong number of annotations");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, header->namespace))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_HEADER,
+ "Invalid namespace name");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean validate_type_blob (GTypelib *metadata,
+ guint32 offset,
+ guint32 signature_offset,
+ gboolean return_type,
+ GError **error);
+
+static gboolean
+validate_array_type_blob (GTypelib *metadata,
+ guint32 offset,
+ guint32 signature_offset,
+ gboolean return_type,
+ GError **error)
+{
+ ArrayTypeBlob *blob;
+
+ blob = (ArrayTypeBlob*)&metadata->data[offset];
+
+ if (!blob->pointer)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Pointer type exected for tag %d", blob->tag);
+ return FALSE;
+ }
+
+ /* FIXME validate length */
+
+ if (!validate_type_blob (metadata,
+ offset + G_STRUCT_OFFSET (ArrayTypeBlob, type),
+ 0, FALSE, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_iface_type_blob (GTypelib *metadata,
+ guint32 offset,
+ guint32 signature_offset,
+ gboolean return_type,
+ GError **error)
+{
+ InterfaceTypeBlob *blob;
+ Header *header;
+
+ header = (Header *)metadata->data;
+
+ blob = (InterfaceTypeBlob*)&metadata->data[offset];
+
+ if (blob->interface == 0 || blob->interface > header->n_entries)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid directory index %d", blob->interface);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_param_type_blob (GTypelib *metadata,
+ guint32 offset,
+ guint32 signature_offset,
+ gboolean return_type,
+ gint n_params,
+ GError **error)
+{
+ ParamTypeBlob *blob;
+ gint i;
+
+ blob = (ParamTypeBlob*)&metadata->data[offset];
+
+ if (!blob->pointer)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Pointer type exected for tag %d", blob->tag);
+ return FALSE;
+ }
+
+ if (blob->n_types != n_params)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Parameter type number mismatch");
+ return FALSE;
+ }
+
+ for (i = 0; i < n_params; i++)
+ {
+ if (!validate_type_blob (metadata,
+ offset + sizeof (ParamTypeBlob) +
+ i * sizeof (SimpleTypeBlob),
+ 0, FALSE, error))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_error_type_blob (GTypelib *metadata,
+ guint32 offset,
+ guint32 signature_offset,
+ gboolean return_type,
+ GError **error)
+{
+ ErrorTypeBlob *blob;
+ Header *header;
+ gint i;
+ DirEntry *entry;
+
+ blob = (ErrorTypeBlob*)&metadata->data[offset];
+
+ header = (Header *)metadata->data;
+
+ if (!blob->pointer)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Pointer type exected for tag %d", blob->tag);
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_domains; i++)
+ {
+ if (blob->domains[i] == 0 || blob->domains[i] > header->n_entries)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid directory index %d", blob->domains[i]);
+ return FALSE;
+ }
+
+ entry = g_typelib_get_dir_entry (metadata, blob->domains[i]);
+
+ if (entry->blob_type != BLOB_TYPE_ERROR_DOMAIN &&
+ (entry->local || entry->blob_type != BLOB_TYPE_INVALID))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Wrong blob type");
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_type_blob (GTypelib *metadata,
+ guint32 offset,
+ guint32 signature_offset,
+ gboolean return_type,
+ GError **error)
+{
+ SimpleTypeBlob *simple;
+ InterfaceTypeBlob *iface;
+
+ simple = (SimpleTypeBlob *)&metadata->data[offset];
+
+ if (simple->reserved == 0 &&
+ simple->reserved2 == 0)
+ {
+ if (simple->tag >= TYPE_TAG_ARRAY)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Wrong tag in simple type");
+ return FALSE;
+ }
+
+ if (simple->tag >= TYPE_TAG_UTF8 &&
+ !simple->pointer)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Pointer type exected for tag %d", simple->tag);
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ iface = (InterfaceTypeBlob*)&metadata->data[simple->offset];
+
+ switch (iface->tag)
+ {
+ case TYPE_TAG_ARRAY:
+ if (!validate_array_type_blob (metadata, simple->offset,
+ signature_offset, return_type, error))
+ return FALSE;
+ break;
+ case TYPE_TAG_INTERFACE:
+ if (!validate_iface_type_blob (metadata, simple->offset,
+ signature_offset, return_type, error))
+ return FALSE;
+ break;
+ case TYPE_TAG_LIST:
+ case TYPE_TAG_SLIST:
+ if (!validate_param_type_blob (metadata, simple->offset,
+ signature_offset, return_type, 1, error))
+ return FALSE;
+ break;
+ case TYPE_TAG_HASH:
+ if (!validate_param_type_blob (metadata, simple->offset,
+ signature_offset, return_type, 2, error))
+ return FALSE;
+ break;
+ case TYPE_TAG_ERROR:
+ if (!validate_error_type_blob (metadata, simple->offset,
+ signature_offset, return_type, error))
+ return FALSE;
+ break;
+ default:
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Wrong tag in complex type");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_arg_blob (GTypelib *metadata,
+ guint32 offset,
+ guint32 signature_offset,
+ GError **error)
+{
+ ArgBlob *blob;
+
+ if (metadata->len < offset + sizeof (ArgBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (ArgBlob*) &metadata->data[offset];
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid argument name");
+ return FALSE;
+ }
+
+ if (!validate_type_blob (metadata,
+ offset + G_STRUCT_OFFSET (ArgBlob, arg_type),
+ signature_offset, FALSE, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_signature_blob (GTypelib *metadata,
+ guint32 offset,
+ GError **error)
+{
+ SignatureBlob *blob;
+ gint i;
+
+ if (metadata->len < offset + sizeof (SignatureBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (SignatureBlob*) &metadata->data[offset];
+
+ if (blob->return_type.offset != 0)
+ {
+ if (!validate_type_blob (metadata,
+ offset + G_STRUCT_OFFSET (SignatureBlob, return_type),
+ offset, TRUE, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_arguments; i++)
+ {
+ if (!validate_arg_blob (metadata,
+ offset + sizeof (SignatureBlob) +
+ i * sizeof (ArgBlob),
+ offset,
+ error))
+ return FALSE;
+ }
+
+ /* FIXME check constraints on return_value */
+ /* FIXME check array-length pairs */
+ return TRUE;
+}
+
+static gboolean
+validate_function_blob (GTypelib *metadata,
+ guint32 offset,
+ guint16 container_type,
+ GError **error)
+{
+ FunctionBlob *blob;
+
+ if (metadata->len < offset + sizeof (FunctionBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (FunctionBlob*) &metadata->data[offset];
+
+ if (blob->blob_type != BLOB_TYPE_FUNCTION)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Wrong blob type");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid function name");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->symbol))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid function symbol");
+ return FALSE;
+ }
+
+ if (blob->constructor)
+ {
+ switch (container_type)
+ {
+ case BLOB_TYPE_BOXED:
+ case BLOB_TYPE_OBJECT:
+ case BLOB_TYPE_INTERFACE:
+ break;
+ default:
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Constructor not allowed");
+ return FALSE;
+ }
+ }
+
+ if (blob->setter || blob->getter || blob->wraps_vfunc)
+ {
+ switch (container_type)
+ {
+ case BLOB_TYPE_OBJECT:
+ case BLOB_TYPE_INTERFACE:
+ break;
+ default:
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Setter, getter or wrapper not allowed");
+ return FALSE;
+ }
+ }
+
+ if (blob->index)
+ {
+ if (!(blob->setter || blob->getter || blob->wraps_vfunc))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Must be setter, getter or wrapper");
+ return FALSE;
+ }
+ }
+
+ /* FIXME: validate index range */
+ /* FIXME: validate "this" argument for methods */
+ /* FIXME: validate return type for constructors */
+
+ if (!validate_signature_blob (metadata, blob->signature, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_callback_blob (GTypelib *metadata,
+ guint32 offset,
+ GError **error)
+{
+ CallbackBlob *blob;
+
+ if (metadata->len < offset + sizeof (CallbackBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (CallbackBlob*) &metadata->data[offset];
+
+ if (blob->blob_type != BLOB_TYPE_CALLBACK)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Wrong blob type");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid callback name");
+ return FALSE;
+ }
+
+ if (!validate_signature_blob (metadata, blob->signature, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_constant_blob (GTypelib *metadata,
+ guint32 offset,
+ GError **error)
+{
+ gint value_size[] = {
+ 0, 4, 1, 1, 2, 2, 4, 4, 8, 8,
+ sizeof (gint), sizeof (guint),
+ sizeof (glong), sizeof (gulong),
+ sizeof (gssize), sizeof (gsize),
+ sizeof (gfloat), sizeof (gdouble),
+ 0, 0
+ };
+ ConstantBlob *blob;
+ SimpleTypeBlob *type;
+
+ if (metadata->len < offset + sizeof (ConstantBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (ConstantBlob*) &metadata->data[offset];
+
+ if (blob->blob_type != BLOB_TYPE_CONSTANT)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Wrong blob type");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid constant name");
+ return FALSE;
+ }
+
+ if (!validate_type_blob (metadata, offset + G_STRUCT_OFFSET (ConstantBlob, type),
+ 0, FALSE, error))
+ return FALSE;
+
+ if (!is_aligned (blob->offset))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Misaligned constant value");
+ return FALSE;
+ }
+
+ type = (SimpleTypeBlob *)&metadata->data[offset + G_STRUCT_OFFSET (ConstantBlob, type)];
+ if (type->reserved == 0)
+ {
+ if (type->tag == 0)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Constant value type void");
+ return FALSE;
+ }
+
+ if (value_size[type->tag] != 0 &&
+ blob->size != value_size[type->tag])
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Constant value size mismatch");
+ return FALSE;
+ }
+ /* FIXME check string values */
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_value_blob (GTypelib *metadata,
+ guint32 offset,
+ GError **error)
+{
+ ValueBlob *blob;
+
+ if (metadata->len < offset + sizeof (ValueBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (ValueBlob*) &metadata->data[offset];
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid value name");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_field_blob (GTypelib *metadata,
+ guint32 offset,
+ GError **error)
+{
+ FieldBlob *blob;
+
+ if (metadata->len < offset + sizeof (FieldBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (FieldBlob*) &metadata->data[offset];
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid field name");
+ return FALSE;
+ }
+
+ if (!validate_type_blob (metadata,
+ offset + G_STRUCT_OFFSET (FieldBlob, type),
+ 0, FALSE, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_property_blob (GTypelib *metadata,
+ guint32 offset,
+ GError **error)
+{
+ PropertyBlob *blob;
+
+ if (metadata->len < offset + sizeof (PropertyBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (PropertyBlob*) &metadata->data[offset];
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid property name");
+ return FALSE;
+ }
+
+ if (!validate_type_blob (metadata,
+ offset + G_STRUCT_OFFSET (PropertyBlob, type),
+ 0, FALSE, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_signal_blob (GTypelib *metadata,
+ guint32 offset,
+ guint32 container_offset,
+ GError **error)
+{
+ SignalBlob *blob;
+ gint n_signals;
+
+ if (metadata->len < offset + sizeof (SignalBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (SignalBlob*) &metadata->data[offset];
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid signal name");
+ return FALSE;
+ }
+
+ if ((blob->run_first != 0) +
+ (blob->run_last != 0) +
+ (blob->run_cleanup != 0) != 1)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid signal run flags");
+ return FALSE;
+ }
+
+ if (blob->has_class_closure)
+ {
+ if (((CommonBlob*)&metadata->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
+ {
+ ObjectBlob *object;
+
+ object = (ObjectBlob*)&metadata->data[container_offset];
+
+ n_signals = object->n_signals;
+ }
+ else
+ {
+ InterfaceBlob *iface;
+
+ iface = (InterfaceBlob*)&metadata->data[container_offset];
+
+ n_signals = iface->n_signals;
+ }
+
+ if (blob->class_closure >= n_signals)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid class closure index");
+ return FALSE;
+ }
+ }
+
+ if (!validate_signature_blob (metadata, blob->signature, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_vfunc_blob (GTypelib *metadata,
+ guint32 offset,
+ guint32 container_offset,
+ GError **error)
+{
+ VFuncBlob *blob;
+ gint n_vfuncs;
+
+ if (metadata->len < offset + sizeof (VFuncBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (VFuncBlob*) &metadata->data[offset];
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid vfunc name");
+ return FALSE;
+ }
+
+ if (blob->class_closure)
+ {
+ if (((CommonBlob*)&metadata->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
+ {
+ ObjectBlob *object;
+
+ object = (ObjectBlob*)&metadata->data[container_offset];
+
+ n_vfuncs = object->n_vfuncs;
+ }
+ else
+ {
+ InterfaceBlob *iface;
+
+ iface = (InterfaceBlob*)&metadata->data[container_offset];
+
+ n_vfuncs = iface->n_vfuncs;
+ }
+
+ if (blob->class_closure >= n_vfuncs)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid class closure index");
+ return FALSE;
+ }
+ }
+
+ if (!validate_signature_blob (metadata, blob->signature, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_struct_blob (GTypelib *metadata,
+ guint32 offset,
+ guint16 blob_type,
+ GError **error)
+{
+ StructBlob *blob;
+ gint i;
+
+ if (metadata->len < offset + sizeof (StructBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (StructBlob*) &metadata->data[offset];
+
+ if (blob->blob_type != blob_type)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Wrong blob type");
+ return FALSE;
+ }
+
+ if ((blob->blob_type == BLOB_TYPE_BOXED && blob->unregistered) ||
+ (blob->blob_type == BLOB_TYPE_STRUCT && !blob->unregistered))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Registration/blob type mismatch");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid struct name");
+ return FALSE;
+ }
+
+ if (blob_type == BLOB_TYPE_BOXED)
+ {
+ if (!is_name (metadata->data, blob->gtype_name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid boxed type name");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->gtype_init))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid boxed type init");
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (blob->gtype_name || blob->gtype_init)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Gtype data in struct");
+ return FALSE;
+ }
+ }
+
+ if (metadata->len < offset + sizeof (StructBlob) +
+ blob->n_fields * sizeof (FieldBlob) +
+ blob->n_methods * sizeof (FunctionBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_fields; i++)
+ {
+ if (!validate_field_blob (metadata,
+ offset + sizeof (StructBlob) +
+ i * sizeof (FieldBlob),
+ error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_methods; i++)
+ {
+ if (!validate_function_blob (metadata,
+ offset + sizeof (StructBlob) +
+ blob->n_fields * sizeof (FieldBlob) +
+ i * sizeof (FunctionBlob),
+ blob_type,
+ error))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_enum_blob (GTypelib *metadata,
+ guint32 offset,
+ guint16 blob_type,
+ GError **error)
+{
+ EnumBlob *blob;
+ ValueBlob *v1, *v2;
+ gint i, j;
+
+ if (metadata->len < offset + sizeof (EnumBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (EnumBlob*) &metadata->data[offset];
+
+ if (blob->blob_type != blob_type)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Wrong blob type");
+ return FALSE;
+ }
+
+ if (!blob->unregistered)
+ {
+ if (!is_name (metadata->data, blob->gtype_name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid enum type name");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->gtype_init))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid enum type init");
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (blob->gtype_name || blob->gtype_init)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Gtype data in unregistered enum");
+ return FALSE;
+ }
+ }
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid enum name");
+ return FALSE;
+ }
+
+ if (metadata->len < offset + sizeof (EnumBlob) +
+ blob->n_values * sizeof (ValueBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_values; i++)
+ {
+ if (!validate_value_blob (metadata,
+ offset + sizeof (EnumBlob) +
+ i * sizeof (ValueBlob),
+ error))
+ return FALSE;
+
+ v1 = (ValueBlob *)&metadata->data[offset + sizeof (EnumBlob) +
+ i * sizeof (ValueBlob)];
+ for (j = 0; j < i; j++)
+ {
+ v2 = (ValueBlob *)&metadata->data[offset + sizeof (EnumBlob) +
+ j * sizeof (ValueBlob)];
+
+ if (v1->value == v2->value)
+ {
+ /* FIXME should this be an error ? */
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Duplicate enum value");
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_object_blob (GTypelib *metadata,
+ guint32 offset,
+ GError **error)
+{
+ Header *header;
+ ObjectBlob *blob;
+ gint i;
+ guint32 offset2;
+
+ header = (Header *)metadata->data;
+
+ if (metadata->len < offset + sizeof (ObjectBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (ObjectBlob*) &metadata->data[offset];
+
+ if (blob->blob_type != BLOB_TYPE_OBJECT)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Wrong blob type");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->gtype_name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid object type name");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->gtype_init))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid object type init");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid object name");
+ return FALSE;
+ }
+
+ if (blob->parent > header->n_entries)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid parent index");
+ return FALSE;
+ }
+
+ if (blob->parent != 0)
+ {
+ DirEntry *entry;
+
+ entry = g_typelib_get_dir_entry (metadata, blob->parent);
+ if (entry->blob_type != BLOB_TYPE_OBJECT &&
+ (entry->local || entry->blob_type != 0))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Parent not object");
+ return FALSE;
+ }
+ }
+
+ if (metadata->len < offset + sizeof (ObjectBlob) +
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2 +
+ blob->n_fields * sizeof (FieldBlob) +
+ blob->n_properties * sizeof (PropertyBlob) +
+ blob->n_methods * sizeof (FunctionBlob) +
+ blob->n_signals * sizeof (SignalBlob) +
+ blob->n_vfuncs * sizeof (VFuncBlob) +
+ blob->n_constants * sizeof (ConstantBlob))
+
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ offset2 = offset + sizeof (ObjectBlob);
+
+ for (i = 0; i < blob->n_interfaces; i++, offset2 += 2)
+ {
+ guint16 iface;
+ DirEntry *entry;
+
+ iface = *(guint16*)&metadata->data[offset2];
+ if (iface == 0 || iface > header->n_entries)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid interface index");
+ return FALSE;
+ }
+
+ entry = g_typelib_get_dir_entry (metadata, iface);
+
+ if (entry->blob_type != BLOB_TYPE_INTERFACE &&
+ (entry->local || entry->blob_type != 0))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Not an interface");
+ return FALSE;
+ }
+ }
+
+ offset2 += 2 * (blob->n_interfaces %2);
+
+ for (i = 0; i < blob->n_fields; i++, offset2 += sizeof (FieldBlob))
+ {
+ if (!validate_field_blob (metadata, offset2, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
+ {
+ if (!validate_property_blob (metadata, offset2, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
+ {
+ if (!validate_function_blob (metadata, offset2, BLOB_TYPE_OBJECT, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
+ {
+ if (!validate_signal_blob (metadata, offset2, offset, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
+ {
+ if (!validate_vfunc_blob (metadata, offset2, offset, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
+ {
+ if (!validate_constant_blob (metadata, offset2, error))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_interface_blob (GTypelib *metadata,
+ guint32 offset,
+ GError **error)
+{
+ Header *header;
+ InterfaceBlob *blob;
+ gint i;
+ guint32 offset2;
+
+ header = (Header *)metadata->data;
+
+ if (metadata->len < offset + sizeof (InterfaceBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ blob = (InterfaceBlob*) &metadata->data[offset];
+
+ if (blob->blob_type != BLOB_TYPE_INTERFACE)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Wrong blob type");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->gtype_name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid interface type name");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->gtype_init))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid interface type init");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, blob->name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid interface name");
+ return FALSE;
+ }
+
+ if (metadata->len < offset + sizeof (InterfaceBlob) +
+ (blob->n_prerequisites + blob->n_prerequisites % 2) * 2 +
+ blob->n_properties * sizeof (PropertyBlob) +
+ blob->n_methods * sizeof (FunctionBlob) +
+ blob->n_signals * sizeof (SignalBlob) +
+ blob->n_vfuncs * sizeof (VFuncBlob) +
+ blob->n_constants * sizeof (ConstantBlob))
+
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ offset2 = offset + sizeof (InterfaceBlob);
+
+ for (i = 0; i < blob->n_prerequisites; i++, offset2 += 2)
+ {
+ DirEntry *entry;
+ guint16 req;
+
+ req = *(guint16*)&metadata->data[offset2];
+ if (req == 0 || req > header->n_entries)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Invalid prerequisite index");
+ return FALSE;
+ }
+
+ entry = g_typelib_get_dir_entry (metadata, req);
+ if (entry->blob_type != BLOB_TYPE_INTERFACE &&
+ entry->blob_type != BLOB_TYPE_OBJECT &&
+ (entry->local || entry->blob_type != 0))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_BLOB,
+ "Not an interface or object");
+ return FALSE;
+ }
+ }
+
+ offset2 += 2 * (blob->n_prerequisites % 2);
+
+ for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
+ {
+ if (!validate_property_blob (metadata, offset2, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
+ {
+ if (!validate_function_blob (metadata, offset2, BLOB_TYPE_INTERFACE, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
+ {
+ if (!validate_signal_blob (metadata, offset2, offset, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
+ {
+ if (!validate_vfunc_blob (metadata, offset2, offset, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
+ {
+ if (!validate_constant_blob (metadata, offset2, error))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_errordomain_blob (GTypelib *metadata,
+ guint32 offset,
+ GError **error)
+{
+ return TRUE;
+}
+
+static gboolean
+validate_union_blob (GTypelib *metadata,
+ guint32 offset,
+ GError **error)
+{
+ return TRUE;
+}
+
+static gboolean
+validate_blob (GTypelib *metadata,
+ guint32 offset,
+ GError **error)
+{
+ CommonBlob *common;
+
+ if (metadata->len < offset + sizeof (CommonBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ common = (CommonBlob*)&metadata->data[offset];
+
+ switch (common->blob_type)
+ {
+ case BLOB_TYPE_FUNCTION:
+ if (!validate_function_blob (metadata, offset, 0, error))
+ return FALSE;
+ break;
+ case BLOB_TYPE_CALLBACK:
+ if (!validate_callback_blob (metadata, offset, error))
+ return FALSE;
+ break;
+ case BLOB_TYPE_STRUCT:
+ case BLOB_TYPE_BOXED:
+ if (!validate_struct_blob (metadata, offset, common->blob_type, error))
+ return FALSE;
+ break;
+ case BLOB_TYPE_ENUM:
+ case BLOB_TYPE_FLAGS:
+ if (!validate_enum_blob (metadata, offset, common->blob_type, error))
+ return FALSE;
+ break;
+ case BLOB_TYPE_OBJECT:
+ if (!validate_object_blob (metadata, offset, error))
+ return FALSE;
+ break;
+ case BLOB_TYPE_INTERFACE:
+ if (!validate_interface_blob (metadata, offset, error))
+ return FALSE;
+ break;
+ case BLOB_TYPE_CONSTANT:
+ if (!validate_constant_blob (metadata, offset, error))
+ return FALSE;
+ break;
+ case BLOB_TYPE_ERROR_DOMAIN:
+ if (!validate_errordomain_blob (metadata, offset, error))
+ return FALSE;
+ break;
+ case BLOB_TYPE_UNION:
+ if (!validate_union_blob (metadata, offset, error))
+ return FALSE;
+ break;
+ default:
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_ENTRY,
+ "Invalid blob type");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_directory (GTypelib *metadata,
+ GError **error)
+{
+ Header *header = (Header *)metadata->data;
+ DirEntry *entry;
+ gint i;
+
+ if (metadata->len < header->directory + header->n_entries * sizeof (DirEntry))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ for (i = 0; i < header->n_entries; i++)
+ {
+ entry = g_typelib_get_dir_entry (metadata, i + 1);
+
+ if (!is_name (metadata->data, entry->name))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_DIRECTORY,
+ "Invalid entry name");
+ return FALSE;
+ }
+
+ if ((entry->local && entry->blob_type == BLOB_TYPE_INVALID) ||
+ entry->blob_type > BLOB_TYPE_UNION)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_DIRECTORY,
+ "Invalid entry type");
+ return FALSE;
+ }
+
+ if (i < header->n_local_entries)
+ {
+ if (!entry->local)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_DIRECTORY,
+ "Too few local directory entries");
+ return FALSE;
+ }
+
+ if (!is_aligned (entry->offset))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_DIRECTORY,
+ "Misaligned entry");
+ return FALSE;
+ }
+
+ if (!validate_blob (metadata, entry->offset, error))
+ return FALSE;
+ }
+ else
+ {
+ if (entry->local)
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_DIRECTORY,
+ "Too many local directory entries");
+ return FALSE;
+ }
+
+ if (!is_name (metadata->data, entry->offset))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID_DIRECTORY,
+ "Invalid namespace name");
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+validate_annotations (GTypelib *metadata,
+ GError **error)
+{
+ Header *header = (Header *)metadata->data;
+
+ if (header->size < header->annotations + header->n_annotations * sizeof (AnnotationBlob))
+ {
+ g_set_error (error,
+ G_TYPELIB_ERROR,
+ G_TYPELIB_ERROR_INVALID,
+ "The buffer is too short");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+g_typelib_validate (GTypelib *metadata,
+ GError **error)
+{
+ if (!validate_header (metadata, error))
+ return FALSE;
+
+ if (!validate_directory (metadata, error))
+ return FALSE;
+
+ if (!validate_annotations (metadata, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+GQuark
+g_typelib_error_quark (void)
+{
+ static GQuark quark = 0;
+ if (quark == 0)
+ quark = g_quark_from_static_string ("g-metadata-error-quark");
+ return quark;
+}
+
+static const char*
+find_some_symbol (GTypelib *metadata)
+{
+ Header *header = (Header *) metadata->data;
+ gint i;
+
+ for (i = 0; i < header->n_entries; i++)
+ {
+ DirEntry *entry;
+
+ entry = g_typelib_get_dir_entry (metadata, i + 1);
+
+ switch (entry->blob_type)
+ {
+ case BLOB_TYPE_FUNCTION:
+ {
+ FunctionBlob *blob = (FunctionBlob *) &metadata->data[entry->offset];
+
+ if (blob->symbol)
+ return g_typelib_get_string (metadata, blob->symbol);
+ }
+ break;
+ case BLOB_TYPE_OBJECT:
+ {
+ RegisteredTypeBlob *blob = (RegisteredTypeBlob *) &metadata->data[entry->offset];
+
+ if (blob->gtype_init)
+ return g_typelib_get_string (metadata, blob->gtype_init);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+static inline void
+_g_typelib_init (GTypelib *metadata)
+{
+ Header *header;
+
+ header = (Header *) metadata->data;
+ if (header->shared_library)
+ {
+ const gchar *shlib;
+
+ shlib = g_typelib_get_string (metadata, header->shared_library);
+ /* note that NULL shlib means to open the main app, which is allowed */
+
+ /* If we do have a shared lib, first be sure the main app isn't already linked to it */
+ if (shlib != NULL)
+ {
+ const char *symbol_in_module;
+
+ symbol_in_module = find_some_symbol (metadata);
+ if (symbol_in_module != NULL)
+ {
+ metadata->module = g_module_open (NULL, G_MODULE_BIND_LAZY);
+ if (metadata->module == NULL)
+ {
+ g_warning ("Could not open main app as GModule: %s",
+ g_module_error ());
+ }
+ else
+ {
+ void *sym;
+ if (!g_module_symbol (metadata->module, symbol_in_module, &sym))
+ {
+ /* we will try opening the shlib, symbol is not in app already */
+ g_module_close (metadata->module);
+ metadata->module = NULL;
+ }
+ }
+ }
+ else
+ {
+ g_warning ("Could not find any symbols in metadata");
+ }
+ }
+
+ if (metadata->module == NULL)
+ {
+ /* Glade's autoconnect feature and OpenGL's extension mechanism
+ * as used by Clutter rely on dlopen(NULL) to work as a means of
+ * accessing the app's symbols. This keeps us from using
+ * G_MODULE_BIND_LOCAL. BIND_LOCAL may have other issues as well;
+ * in general libraries are not expecting multiple copies of
+ * themselves and are not expecting to be unloaded. So we just
+ * load modules globally for now.
+ */
+
+ metadata->module = g_module_open (shlib, G_MODULE_BIND_LAZY);
+ if (metadata->module == NULL)
+ g_warning ("Failed to load shared library referenced by the metadata: %s",
+ g_module_error ());
+ }
+ }
+}
+
+/**
+ * g_typelib_new_from_memory:
+ * @memory: address of memory chunk containing the metadata
+ * @len: length of memory chunk containing the metadata
+ *
+ * Creates a new #GTypelib from a memory location. The memory block
+ * pointed to by @metadata will be automatically g_free()d when the
+ * repository is destroyed.
+ *
+ * Return value: the new #GTypelib
+ **/
+GTypelib *
+g_typelib_new_from_memory (guchar *memory, gsize len)
+{
+ GTypelib *meta;
+
+ meta = g_new0 (GTypelib, 1);
+ meta->data = memory;
+ meta->len = len;
+ meta->owns_memory = TRUE;
+ _g_typelib_init (meta);
+ return meta;
+}
+
+/**
+ * g_typelib_new_from_const_memory:
+ * @memory: address of memory chunk containing the metadata
+ * @len: length of memory chunk containing the metadata
+ *
+ * Creates a new #GTypelib from a memory location.
+ *
+ * Return value: the new #GTypelib
+ **/
+GTypelib *
+g_typelib_new_from_const_memory (const guchar *memory, gsize len)
+{
+ GTypelib *meta;
+
+ meta = g_new0 (GTypelib, 1);
+ meta->data = (guchar *) memory;
+ meta->len = len;
+ meta->owns_memory = FALSE;
+ _g_typelib_init (meta);
+ return meta;
+}
+
+/**
+ * g_typelib_new_from_mapped_file:
+ * @mfile: a #GMappedFile, that will be free'd when the repository is destroyed
+ *
+ * Creates a new #GTypelib from a #GMappedFile.
+ *
+ * Return value: the new #GTypelib
+ **/
+GTypelib *
+g_typelib_new_from_mapped_file (GMappedFile *mfile)
+{
+ GTypelib *meta;
+
+ meta = g_new0 (GTypelib, 1);
+ meta->mfile = mfile;
+ meta->owns_memory = FALSE;
+ meta->data = (guchar *) g_mapped_file_get_contents (mfile);
+ meta->len = g_mapped_file_get_length (mfile);
+ _g_typelib_init (meta);
+ return meta;
+}
+
+/**
+ * g_typelib_free:
+ * @metadata: a #GTypelib
+ *
+ * Free a #GTypelib.
+ **/
+void
+g_typelib_free (GTypelib *metadata)
+{
+ if (metadata->mfile)
+ g_mapped_file_free (metadata->mfile);
+ else
+ if (metadata->owns_memory)
+ g_free (metadata->data);
+ if (metadata->module)
+ g_module_close (metadata->module);
+ g_free (metadata);
+}
+
+/**
+ * g_typelib_set_module:
+ * @metadata: a #GTypelib instance
+ * @module: a #GModule; takes ownership of this module
+ *
+ * Sets the target module for all symbols referenced by the metadata.
+ **/
+void
+g_typelib_set_module (GTypelib *metadata, GModule *module)
+{
+ if (metadata->module)
+ g_module_close (metadata->module);
+ metadata->module = module;
+}
+
+const gchar *
+g_typelib_get_namespace(GTypelib *metadata)
+{
+ return g_typelib_get_string (metadata, ((Header *) metadata->data)->namespace);
+}
Added: trunk/girepository/gtypelib.h
==============================================================================
--- (empty file)
+++ trunk/girepository/gtypelib.h Sun Jun 8 14:37:30 2008
@@ -0,0 +1,549 @@
+/* GObject introspection: struct definitions for the binary
+ * metadata format, validation
+ *
+ * Copyright (C) 2005 Matthias Clasen
+ *
+ * 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_TYPELIB_H__
+#define __G_TYPELIB_H__
+
+#include <gmodule.h>
+#include "girepository.h"
+
+G_BEGIN_DECLS
+
+#define G_IDL_MAGIC "GOBJ\nMETADATA\r\n\032"
+
+enum
+{
+ BLOB_TYPE_INVALID,
+ BLOB_TYPE_FUNCTION,
+ BLOB_TYPE_CALLBACK,
+ BLOB_TYPE_STRUCT,
+ BLOB_TYPE_BOXED,
+ BLOB_TYPE_ENUM,
+ BLOB_TYPE_FLAGS,
+ BLOB_TYPE_OBJECT,
+ BLOB_TYPE_INTERFACE,
+ BLOB_TYPE_CONSTANT,
+ BLOB_TYPE_ERROR_DOMAIN,
+ BLOB_TYPE_UNION
+};
+
+typedef struct
+{
+ gchar magic[16];
+ guint8 major_version;
+ guint8 minor_version;
+ guint16 reserved;
+ guint16 n_entries;
+ guint16 n_local_entries;
+ guint32 directory;
+ guint32 n_annotations;
+ guint32 annotations;
+
+ guint32 size;
+ guint32 namespace;
+ guint32 shared_library;
+
+ guint16 entry_blob_size;
+ guint16 function_blob_size;
+ guint16 callback_blob_size;
+ guint16 signal_blob_size;
+ guint16 vfunc_blob_size;
+ guint16 arg_blob_size;
+ guint16 property_blob_size;
+ guint16 field_blob_size;
+ guint16 value_blob_size;
+ guint16 annotation_blob_size;
+ guint16 constant_blob_size;
+ guint16 error_domain_blob_size;
+
+ guint16 signature_blob_size;
+ guint16 enum_blob_size;
+ guint16 struct_blob_size;
+ guint16 object_blob_size;
+ guint16 interface_blob_size;
+ guint16 union_blob_size;
+
+ guint16 padding[7];
+} Header;
+
+typedef struct
+{
+ guint16 blob_type;
+
+ guint local : 1;
+ guint reserved :15;
+
+ guint32 name;
+ guint32 offset;
+} DirEntry;
+
+
+#define TYPE_POINTER_MASK 1 << 7
+#define TYPE_TAG_MASK 63
+
+typedef enum
+{
+ TYPE_TAG_VOID = 0,
+ TYPE_TAG_BOOLEAN = 1,
+ TYPE_TAG_INT8 = 2,
+ TYPE_TAG_UINT8 = 3,
+ TYPE_TAG_INT16 = 4,
+ TYPE_TAG_UINT16 = 5,
+ TYPE_TAG_INT32 = 6,
+ TYPE_TAG_UINT32 = 7,
+ TYPE_TAG_INT64 = 8,
+ TYPE_TAG_UINT64 = 9,
+ TYPE_TAG_INT = 10,
+ TYPE_TAG_UINT = 11,
+ TYPE_TAG_LONG = 12,
+ TYPE_TAG_ULONG = 13,
+ TYPE_TAG_SSIZE = 14,
+ TYPE_TAG_SIZE = 15,
+ TYPE_TAG_FLOAT = 16,
+ TYPE_TAG_DOUBLE = 17,
+ TYPE_TAG_UTF8 = 18,
+ TYPE_TAG_FILENAME = 19,
+ TYPE_TAG_ARRAY = 20,
+ TYPE_TAG_INTERFACE = 21,
+ TYPE_TAG_LIST = 22,
+ TYPE_TAG_SLIST = 23,
+ TYPE_TAG_HASH = 24,
+ TYPE_TAG_ERROR = 25
+} TypeTag;
+
+typedef union
+{
+ struct
+ {
+ guint reserved : 8;
+ guint reserved2 :16;
+ guint pointer : 1;
+ guint reserved3 : 2;
+ guint tag : 5;
+ };
+ guint32 offset;
+} SimpleTypeBlob;
+
+
+typedef struct
+{
+ guint32 name;
+
+ guint in : 1;
+ guint out : 1;
+ guint dipper : 1;
+ guint null_ok : 1;
+ guint optional : 1;
+ guint transfer_ownership : 1;
+ guint transfer_container_ownership : 1;
+ guint return_value : 1;
+ guint reserved :24;
+
+ SimpleTypeBlob arg_type;
+} ArgBlob;
+
+typedef struct
+{
+ SimpleTypeBlob return_type;
+
+ guint may_return_null : 1;
+ guint caller_owns_return_value : 1;
+ guint caller_owns_return_container : 1;
+ guint reserved :13;
+
+ guint16 n_arguments;
+
+ ArgBlob arguments[];
+} SignatureBlob;
+
+typedef struct
+{
+ guint16 blob_type; /* 1 */
+
+ guint deprecated : 1;
+ guint reserved :15;
+
+ guint32 name;
+} CommonBlob;
+
+typedef struct
+{
+ guint16 blob_type; /* 1 */
+
+ guint deprecated : 1;
+ guint setter : 1;
+ guint getter : 1;
+ guint constructor : 1;
+ guint wraps_vfunc : 1;
+ guint reserved : 1;
+ guint index :10;
+
+ guint32 name;
+ guint32 symbol;
+ guint32 signature;
+} FunctionBlob;
+
+typedef struct
+{
+ guint16 blob_type; /* 2 */
+
+ guint deprecated : 1;
+ guint reserved :15;
+
+ guint32 name;
+ guint32 signature;
+} CallbackBlob;
+
+typedef struct
+{
+ guint pointer :1;
+ guint reserved :2;
+ guint tag :5;
+ guint8 reserved2;
+ guint16 interface;
+} InterfaceTypeBlob;
+
+typedef struct
+{
+ guint pointer :1;
+ guint reserved :2;
+ guint tag :5;
+
+ guint zero_terminated :1;
+ guint has_length :1;
+ guint reserved2 :6;
+
+ guint16 length;
+
+ SimpleTypeBlob type;
+} ArrayTypeBlob;
+
+typedef struct
+{
+ guint pointer :1;
+ guint reserved :2;
+ guint tag :5;
+
+ guint8 reserved2;
+ guint16 n_types;
+
+ SimpleTypeBlob type[];
+} ParamTypeBlob;
+
+typedef struct
+{
+ guint pointer :1;
+ guint reserved :2;
+ guint tag :5;
+
+ guint8 reserved2;
+ guint16 n_domains;
+
+ guint16 domains[];
+} ErrorTypeBlob;
+
+typedef struct
+{
+ guint16 blob_type; /* 10 */
+
+ guint deprecated : 1;
+ guint reserved :15;
+
+ guint32 name;
+
+ guint32 get_quark;
+ guint16 error_codes;
+ guint16 reserved2;
+} ErrorDomainBlob;
+
+typedef struct
+{
+ guint deprecated : 1;
+ guint reserved :31;
+ guint32 name;
+ guint32 value;
+} ValueBlob;
+
+typedef struct
+{
+ guint32 name;
+
+ guint readable : 1;
+ guint writable : 1;
+ guint reserved : 6;
+ guint8 bits;
+
+ guint16 struct_offset;
+
+ SimpleTypeBlob type;
+} FieldBlob;
+
+typedef struct
+{
+ guint16 blob_type;
+ guint deprecated : 1;
+ guint unregistered :15;
+ guint32 name;
+
+ guint32 gtype_name;
+ guint32 gtype_init;
+} RegisteredTypeBlob;
+
+typedef struct
+{
+ guint16 blob_type;
+
+ guint deprecated : 1;
+ guint unregistered : 1;
+ guint reserved :14;
+
+ guint32 name;
+
+ guint32 gtype_name;
+ guint32 gtype_init;
+
+ guint16 n_fields;
+ guint16 n_methods;
+
+#if 0
+ /* variable-length parts of the blob */
+ FieldBlob fields[];
+ FunctionBlob methods[];
+#endif
+} StructBlob;
+
+typedef struct
+{
+ guint16 blob_type;
+ guint deprecated : 1;
+ guint unregistered : 1;
+ guint discriminated : 1;
+ guint reserved :13;
+ guint32 name;
+
+ guint32 gtype_name;
+ guint32 gtype_init;
+
+ guint16 n_fields;
+ guint16 n_functions;
+
+ gint32 discriminator_offset;
+ SimpleTypeBlob discriminator_type;
+
+#if 0
+ FieldBlob fields[];
+ FunctionBlob functions[];
+ ConstantBlob discriminator_values[]
+#endif
+} UnionBlob;
+
+typedef struct
+{
+ guint16 blob_type;
+
+ guint deprecated : 1;
+ guint unregistered : 1;
+ guint reserved :14;
+
+ guint32 name;
+
+ guint32 gtype_name;
+ guint32 gtype_init;
+
+ guint16 n_values;
+ guint16 reserved2;
+
+ ValueBlob values[];
+} EnumBlob;
+
+typedef struct
+{
+ guint32 name;
+
+ guint deprecated : 1;
+ guint readable : 1;
+ guint writable : 1;
+ guint construct : 1;
+ guint construct_only : 1;
+ guint reserved :27;
+
+ SimpleTypeBlob type;
+
+} PropertyBlob;
+
+typedef struct
+{
+ guint deprecated : 1;
+ guint run_first : 1;
+ guint run_last : 1;
+ guint run_cleanup : 1;
+ guint no_recurse : 1;
+ guint detailed : 1;
+ guint action : 1;
+ guint no_hooks : 1;
+ guint has_class_closure : 1;
+ guint true_stops_emit : 1;
+ guint reserved : 6;
+
+ guint16 class_closure;
+
+ guint32 name;
+
+ guint32 signature;
+} SignalBlob;
+
+typedef struct
+{
+ guint32 name;
+
+ guint must_chain_up : 1;
+ guint must_be_implemented : 1;
+ guint must_not_be_implemented : 1;
+ guint class_closure : 1;
+ guint reserved :12;
+ guint16 signal;
+
+ guint16 struct_offset;
+ guint16 reserved2;
+ guint32 signature;
+} VFuncBlob;
+
+typedef struct
+{
+ guint16 blob_type; /* 7 */
+ guint deprecated : 1;
+ guint reserved :15;
+ guint32 name;
+
+ guint32 gtype_name;
+ guint32 gtype_init;
+
+ guint16 parent;
+
+ guint16 n_interfaces;
+ guint16 n_fields;
+ guint16 n_properties;
+ guint16 n_methods;
+ guint16 n_signals;
+ guint16 n_vfuncs;
+ guint16 n_constants;
+
+ guint16 interfaces[];
+
+#if 0
+ /* variable-length parts of the blob */
+ FieldBlob fields[];
+ PropertyBlob properties[];
+ FunctionBlob methods[];
+ SignalBlob signals[];
+ VFuncBlob vfuncs[];
+ ConstantBlob constants[];
+#endif
+} ObjectBlob;
+
+typedef struct
+{
+ guint16 blob_type;
+ guint deprecated : 1;
+ guint reserved :15;
+ guint32 name;
+
+ guint32 gtype_name;
+ guint32 gtype_init;
+
+ guint16 n_prerequisites;
+ guint16 n_properties;
+ guint16 n_methods;
+ guint16 n_signals;
+ guint16 n_vfuncs;
+ guint16 n_constants;
+
+ guint16 prerequisites[];
+
+#if 0
+ /* variable-length parts of the blob */
+ PropertyBlob properties[];
+ FunctionBlob methods[];
+ SignalBlob signals[];
+ VFuncBlob vfuncs[];
+ ConstantBlob constants[];
+#endif
+} InterfaceBlob;
+
+
+typedef struct
+{
+ guint16 blob_type;
+ guint deprecated : 1;
+ guint reserved :15;
+ guint32 name;
+
+ SimpleTypeBlob type;
+
+ guint32 size;
+ guint32 offset;
+} ConstantBlob;
+
+typedef struct
+{
+ guint32 offset;
+ guint32 name;
+ guint32 value;
+} AnnotationBlob;
+
+
+struct _GTypelib {
+ guchar *data;
+ gsize len;
+ gboolean owns_memory;
+ GMappedFile *mfile;
+ GModule *module;
+};
+
+DirEntry *g_typelib_get_dir_entry (GTypelib *metadata,
+ guint16 index);
+
+void g_typelib_check_sanity (void);
+
+#define g_typelib_get_string(metadata,offset) ((const gchar*)&(metadata->data)[(offset)])
+
+
+typedef enum
+{
+ G_TYPELIB_ERROR_INVALID,
+ G_TYPELIB_ERROR_INVALID_HEADER,
+ G_TYPELIB_ERROR_INVALID_DIRECTORY,
+ G_TYPELIB_ERROR_INVALID_ENTRY,
+ G_TYPELIB_ERROR_INVALID_BLOB
+} GTypelibError;
+
+#define G_TYPELIB_ERROR (g_typelib_error_quark ())
+
+GQuark g_typelib_error_quark (void);
+
+gboolean g_typelib_validate (GTypelib *metadata,
+ GError **error);
+
+
+G_END_DECLS
+
+#endif /* __G_TYPELIB_H__ */
+
Modified: trunk/tools/compiler.c
==============================================================================
--- trunk/tools/compiler.c (original)
+++ trunk/tools/compiler.c Sun Jun 8 14:37:30 2008
@@ -27,7 +27,7 @@
#include "gidlmodule.h"
#include "gidlnode.h"
#include "gidlparser.h"
-#include "gmetadata.h"
+#include "gtypelib.h"
gboolean raw = FALSE;
gboolean no_init = FALSE;
@@ -39,7 +39,7 @@
gboolean verbose = FALSE;
static gchar *
-format_output (GMetadata *metadata)
+format_output (GTypelib *metadata)
{
GString *result;
gint i;
@@ -49,7 +49,7 @@
g_string_append_printf (result, "#include <stdlib.h>\n");
g_string_append_printf (result, "#include <girepository.h>\n\n");
- g_string_append_printf (result, "const unsigned char _G_METADATA[] = \n{");
+ g_string_append_printf (result, "const unsigned char _G_TYPELIB[] = \n{");
for (i = 0; i < metadata->len; i++)
{
@@ -63,7 +63,7 @@
}
g_string_append_printf (result, "\n};\n\n");
- g_string_append_printf (result, "const gsize _G_METADATA_SIZE = %u;\n\n",
+ g_string_append_printf (result, "const gsize _G_TYPELIB_SIZE = %u;\n\n",
(guint)metadata->len);
if (!no_init)
@@ -72,8 +72,8 @@
"__attribute__((constructor)) void\n"
"register_metadata (void)\n"
"{\n"
- "\tGMetadata *metadata;\n"
- "\tmetadata = g_metadata_new_from_const_memory (_G_METADATA, _G_METADATA_SIZE);\n"
+ "\tGTypelib *metadata;\n"
+ "\tmetadata = g_typelib_new_from_const_memory (_G_TYPELIB, _G_TYPELIB_SIZE);\n"
"\tg_irepository_register (NULL, metadata);\n"
"}\n\n");
@@ -83,7 +83,7 @@
"{\n"
"\tg_irepository_unregister (NULL, \"%s\");\n"
"}\n",
- g_metadata_get_namespace (metadata));
+ g_typelib_get_namespace (metadata));
}
return g_string_free (result, FALSE);
@@ -91,7 +91,7 @@
static void
write_out_metadata (gchar *prefix,
- GMetadata *metadata)
+ GTypelib *metadata)
{
FILE *file;
@@ -167,7 +167,7 @@
GError *error = NULL;
GList *c, *m, *modules;
gint i;
- g_metadata_check_sanity ();
+ g_typelib_check_sanity ();
context = g_option_context_new ("");
g_option_context_add_main_entries (context, options, NULL);
@@ -210,7 +210,7 @@
{
GIdlModule *module = m->data;
gchar *prefix;
- GMetadata *metadata;
+ GTypelib *metadata;
if (mname && strcmp (mname, module->name) != 0)
continue;
@@ -227,7 +227,7 @@
continue;
}
- if (!g_metadata_validate (metadata, &error))
+ if (!g_typelib_validate (metadata, &error))
g_error ("Invalid metadata for module '%s': %s",
module->name, error->message);
@@ -237,7 +237,7 @@
prefix = NULL;
write_out_metadata (prefix, metadata);
- g_metadata_free (metadata);
+ g_typelib_free (metadata);
metadata = NULL;
/* when writing to stdout, stop after the first module */
Modified: trunk/tools/generate.c
==============================================================================
--- trunk/tools/generate.c (original)
+++ trunk/tools/generate.c Sun Jun 8 14:37:30 2008
@@ -28,7 +28,7 @@
#include <glib/gstdio.h>
#include "girepository.h"
-#include "gmetadata.h"
+#include "gtypelib.h"
/* FIXME: Avoid global */
static gchar *output = NULL;
@@ -1103,14 +1103,14 @@
GModule *handle;
handle = g_module_open (filename, G_MODULE_BIND_LOCAL|G_MODULE_BIND_LAZY);
- if (!g_module_symbol (handle, "_G_METADATA", (gpointer *) &metadata))
+ if (!g_module_symbol (handle, "_G_TYPELIB", (gpointer *) &metadata))
{
g_printerr ("Could not load metadata from '%s': %s\n",
filename, g_module_error ());
return NULL;
}
- if (!g_module_symbol (handle, "_G_METADATA_SIZE", (gpointer *) &metadata_size))
+ if (!g_module_symbol (handle, "_G_TYPELIB_SIZE", (gpointer *) &metadata_size))
{
g_printerr ("Could not load metadata from '%s': %s\n",
filename, g_module_error ());
@@ -1134,7 +1134,7 @@
GError *error = NULL;
gboolean needs_prefix;
gint i;
- GMetadata *data;
+ GTypelib *data;
GOptionEntry options[] =
{
{ "raw", 0, 0, G_OPTION_ARG_NONE, &raw, "handle raw metadata", NULL },
@@ -1145,7 +1145,7 @@
g_type_init ();
- g_metadata_check_sanity ();
+ g_typelib_check_sanity ();
context = g_option_context_new ("");
g_option_context_add_main_entries (context, options, NULL);
@@ -1190,10 +1190,10 @@
else
needs_prefix = FALSE;
- data = g_metadata_new_from_const_memory (metadata, len);
+ data = g_typelib_new_from_const_memory (metadata, len);
{
GError *error = NULL;
- if (!g_metadata_validate (data, &error)) {
+ if (!g_typelib_validate (data, &error)) {
g_printerr ("metadata not valid: %s\n", error->message);
g_clear_error (&error);
}
@@ -1201,7 +1201,7 @@
g_irepository_register (g_irepository_get_default (), data);
write_repository (g_irepository_get_default (), needs_prefix);
g_irepository_unregister (g_irepository_get_default (),
- g_metadata_get_namespace (data));
+ g_typelib_get_namespace (data));
if (dlhandle)
{
Modified: trunk/tools/gidlmodule.c
==============================================================================
--- trunk/tools/gidlmodule.c (original)
+++ trunk/tools/gidlmodule.c Sun Jun 8 14:37:30 2008
@@ -60,7 +60,7 @@
g_free (module);
}
-GMetadata *
+GTypelib *
g_idl_module_build_metadata (GIdlModule *module,
GList *modules)
{
@@ -210,6 +210,6 @@
metadata = g_realloc (data, offset2);
length = header->size = offset2;
- return g_metadata_new_from_memory (metadata, length);
+ return g_typelib_new_from_memory (metadata, length);
}
Modified: trunk/tools/gidlmodule.h
==============================================================================
--- trunk/tools/gidlmodule.h (original)
+++ trunk/tools/gidlmodule.h Sun Jun 8 14:37:30 2008
@@ -22,7 +22,7 @@
#define __G_IDL_MODULE_H__
#include <glib.h>
-#include "gmetadata.h"
+#include "gtypelib.h"
G_BEGIN_DECLS
@@ -40,7 +40,7 @@
const gchar *module_filename);
void g_idl_module_free (GIdlModule *module);
-GMetadata * g_idl_module_build_metadata (GIdlModule *module,
+GTypelib * g_idl_module_build_metadata (GIdlModule *module,
GList *modules);
G_END_DECLS
Modified: trunk/tools/gidlnode.c
==============================================================================
--- trunk/tools/gidlnode.c (original)
+++ trunk/tools/gidlnode.c Sun Jun 8 14:37:30 2008
@@ -24,7 +24,7 @@
#include "gidlmodule.h"
#include "gidlnode.h"
-#include "gmetadata.h"
+#include "gtypelib.h"
static gulong string_count = 0;
static gulong unique_string_count = 0;
Modified: trunk/tools/gidlparser.c
==============================================================================
--- trunk/tools/gidlparser.c (original)
+++ trunk/tools/gidlparser.c Sun Jun 8 14:37:30 2008
@@ -25,7 +25,7 @@
#include <glib.h>
#include "gidlmodule.h"
#include "gidlnode.h"
-#include "gmetadata.h"
+#include "gtypelib.h"
typedef enum
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]