summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <matthiasc@src.gnome.org>2005-05-09 14:24:46 +0000
committerMatthias Clasen <matthiasc@src.gnome.org>2005-05-09 14:24:46 +0000
commit1675d0574f188d627d1f18d7c1c78279bb4ae102 (patch)
tree7e5ff6e1c60b4e314524e76e25501cb1432fb6a0
downloadgobject-introspection-1675d0574f188d627d1f18d7c1c78279bb4ae102.tar.gz
Initial revision
-rw-r--r--README18
-rw-r--r--TODO30
-rw-r--r--gidl.dtd132
-rw-r--r--metadata-format.txt995
-rw-r--r--src/Makefile38
-rw-r--r--src/compiler.c214
-rw-r--r--src/generate.c999
-rw-r--r--src/gidlmodule.c187
-rw-r--r--src/gidlmodule.h47
-rw-r--r--src/gidlnode.c1749
-rw-r--r--src/gidlnode.h313
-rw-r--r--src/gidlparser.c1884
-rw-r--r--src/gidlparser.h38
-rw-r--r--src/ginfo.c1639
-rw-r--r--src/girepository.c338
-rw-r--r--src/girepository.h388
-rw-r--r--src/gmetadata.c65
-rw-r--r--src/gmetadata.h462
-rw-r--r--tests/Makefile2
-rw-r--r--tests/array.test25
-rw-r--r--tests/boxed.test33
-rw-r--r--tests/enum.test20
-rw-r--r--tests/errors.test22
-rw-r--r--tests/function.test21
-rw-r--r--tests/gobject.test7
-rw-r--r--tests/interface.test38
-rw-r--r--tests/object.test34
-rw-r--r--tests/object.test10
-rwxr-xr-xtests/roundtrips.sh26
-rw-r--r--tests/xref1.test13
-rw-r--r--tests/xref2.test13
31 files changed, 9790 insertions, 0 deletions
diff --git a/README b/README
new file mode 100644
index 00000000..1f07049a
--- /dev/null
+++ b/README
@@ -0,0 +1,18 @@
+This is a very first prototype of an introspection framework for GObject.
+
+The metadata format is described in metadata-format.txt, the XML IDL format
+follows the DTD in gidl.dtd. Look at the files in tests/ for IDL examples.
+
+The code in src/ currently produces three things:
+- g-idl-compile, a metadata compiler. It converts one or more IDL files
+ into one or more metadata blobs. It can either emit the raw metadata
+ blob (--raw) or C code (--code).
+- libirepository, the repository API.
+- g-idl-generate, an IDL generator, using the repository API. It generates
+ IDL files from binary metadata which can be in a shared object, or a raw
+ metadata blob (--raw).
+
+There are a number of IDL test files in test/, and a script to do
+roundtrip tests (IDL -> binary -> IDL).
+
+The introspection framework needs a lot more work, see TODO.
diff --git a/TODO b/TODO
new file mode 100644
index 00000000..8556a0ff
--- /dev/null
+++ b/TODO
@@ -0,0 +1,30 @@
+XML format
+----------
+- Document the format
+- Write a tool to create XML from annotated headers
+- Add attributes to connect signals to their default handlers
+ and wrappers to their vfuncs
+
+Binary format
+-------------
+- Add hashes to lookup interfaces and functions in interfaces
+- Write a validator
+
+Compiler
+--------
+- Cleanup, maybe turn the nodes in to objects to avoid the horrific
+ type switches
+- Add thorough error checking
+
+Repository
+----------
+- Reconsider the current clunky API, maybe an iterator approach is better
+- Add thorough error checking
+- Use hashes
+- Implement g_function_info_invoke()
+- Maybe allow populating repositories at runtime
+
+General
+-------
+- More tests
+- Check how the format scales to something of GTK+ size
diff --git a/gidl.dtd b/gidl.dtd
new file mode 100644
index 00000000..26bd3f0b
--- /dev/null
+++ b/gidl.dtd
@@ -0,0 +1,132 @@
+<!ELEMENT api (namespace+) >
+
+<!ATTLIST api version CDATA #REQUIRED >
+
+<!ELEMENT namespace (function|callback|object|interface|enum|flags|boxed|struct|constant|errordomain)* >
+<!ATTLIST namespace name CDATA #REQUIRED >
+
+<!ELEMENT function (return-type,parameters?) >
+<!ATTLIST function name CDATA #REQUIRED
+ cname CDATA #REQUIRED
+ deprecated (0|1) #IMPLIED >
+<!ELEMENT parameters (parameter+) >
+<!ELEMENT return-type EMPTY >
+<!ATTLIST return-type type CDATA #REQUIRED
+ null-ok (0|1) #IMPLIED
+ transfer (full|shallow|none) #IMPLIED >
+
+
+<!ELEMENT parameter EMPTY >
+<!ATTLIST parameter type CDATA #REQUIRED
+ name CDATA #REQUIRED
+ direction (in|out|inout) #IMPLIED
+ retval (0|1) #IMPLIED
+ dipper (0|1) #IMPLIED
+ optional (0|1) #IMPLIED
+ null-ok (0|1) #IMPLIED
+ transfer (full|shallow|none) #IMPLIED >
+
+<!ELEMENT callback (return-type,parameters?) >
+<!ATTLIST callback name CDATA #REQUIRED
+ cname CDATA #IMPLIED
+ deprecated (0|1) #IMPLIED >
+
+<!ELEMENT object (implements|field|signal|method|property|vfunc|constructor|constant)* >
+<!ATTLIST object name CDATA #IMPLIED
+ cname CDATA #REQUIRED
+ parent CDATA #REQUIRED
+ get-type CDATA #IMPLIED
+ deprecated (0|1) #IMPLIED >
+
+<!ELEMENT implements (interface+) >
+
+<!ELEMENT method (return-type,parameters?) >
+<!ATTLIST method name CDATA #REQUIRED
+ cname CDATA #REQUIRED
+ deprecated (0|1) #IMPLIED
+ type (setter|getter) #IMPLIED >
+
+<!ELEMENT constructor (parameters?) >
+<!ATTLIST constructor name CDATA #REQUIRED
+ cname CDATA #REQUIRED
+ deprecated (0|1) #IMPLIED >
+
+<!ELEMENT interface ((requires|signal|method|property|vfunc|constant)*) >
+<!ATTLIST interface name CDATA #REQUIRED
+ cname CDATA #REQUIRED
+ get-type CDATA #IMPLIED
+ deprecated (0|1) #IMPLIED >
+
+<!ELEMENT requires ((interface|object)*) >
+
+<!ELEMENT property EMPTY >
+<!ATTLIST property name CDATA #REQUIRED
+ cname CDATA #REQUIRED
+ type CDATA #REQUIRED
+ readable (0|1) #IMPLIED
+ writable (0|1) #IMPLIED
+ construct (0|1) #IMPLIED
+ construct-only (0|1) #IMPLIED >
+
+<!ELEMENT signal (return-type,parameters) >
+<!ATTLIST signal name CDATA #REQUIRED
+ cname CDATA #REQUIRED
+ when (FIRST|LAST|CLEANUP) #REQUIRED
+ no-recurse (0|1) #IMPLIED
+ detailed (0|1) #IMPLIED
+ action (0|1) #IMPLIED
+ no-hooks (0|1) #IMPLIED
+ has-class-closure (0|1) #IMPLIED >
+
+<!ELEMENT vfunc (return-type,parameters?) >
+<!ATTLIST vfunc name CDATA #REQUIRED
+ cname CDATA #REQUIRED
+ must-chain-up (0|1) #IMPLIED
+ override (always|never|maybe) #IMPLIED
+ is-class-closure (0|1) #IMPLIED >
+
+<!ELEMENT field EMPTY >
+<!ATTLIST field cname CDATA #REQUIRED
+ type CDATA #REQUIRED
+ bits CDATA #IMPLIED >
+
+<!ELEMENT enum (member+) >
+<!ATTLIST enum name CDATA #REQUIRED
+ cname CDATA #REQUIRED
+ get-type CDATA #IMPLIED
+ deprecated (0|1) #IMPLIED >
+
+
+<!ELEMENT flags (member+) >
+<!ATTLIST flags name CDATA #REQUIRED
+ cname CDATA #REQUIRED
+ get-type CDATA #IMPLIED
+ deprecated (0|1) #IMPLIED >
+
+<!ELEMENT member EMPTY >
+<!ATTLIST member name CDATA #REQUIRED
+ cname CDATA #REQUIRED
+ value CDATA #IMPLIED
+ deprecated (0|1) #IMPLIED >
+
+<!ELEMENT boxed ((field|method)*) >
+<!ATTLIST boxed name CDATA #REQUIRED
+ cname CDATA #REQUIRED
+ get-type CDATA #IMPLIED
+ deprecated (0|1) #IMPLIED >
+
+<!ELEMENT struct ((field|method)*) >
+<!ATTLIST struct name CDATA #REQUIRED
+ cname CDATA #REQUIRED
+ deprecated (0|1) #IMPLIED >
+
+<!ELEMENT constant EMPTY >
+<!ATTLIST constant name CDATA #REQUIRED
+ type CDATA #REQUIRED
+ value CDATA #REQUIRED
+ deprecated (0|1) #IMPLIED >
+
+<!ELEMENT errordomain EMPTY >
+<!ATTLIST errordomain name CDATA #REQUIRED
+ get-quark CDATA #REQUIRED
+ codes CDATA #REQUIRED >
diff --git a/metadata-format.txt b/metadata-format.txt
new file mode 100644
index 00000000..d9b7fd7e
--- /dev/null
+++ b/metadata-format.txt
@@ -0,0 +1,995 @@
+GObject binary metadata for introspection
+-----------------------------------------
+
+Version 0.3
+
+Changes since 0.2:
+- make inline types 4 bytes after all, remove header->types and allow
+ types to appear anywhere
+- allow error domains in the directory
+
+Changes since 0.1:
+
+- drop comments about _GOBJ_METADATA
+- drop string pool, strings can appear anywhere
+- use 'blob' as collective name for the various blob types
+- rename 'type' field in blobs to 'blob_type'
+- rename 'type_name' and 'type_init' fields to 'gtype_name', 'gtype_init'
+- shrink directory entries to 12 bytes
+- merge struct and boxed blobs
+- split interface blobs into enum, object and interface blobs
+- add an 'unregistered' flag to struct and enum blobs
+- add a 'wraps_vfunc' flag to function blobs and link them to
+ the vfuncs they wrap
+- restrict value blobs to only occur inside enums and flags again
+- add constant blobs, allow them toplevel, in interfaces and in objects
+- rename 'receiver_owns_value' and 'receiver_owns_container' to
+ 'transfer_ownership' and 'transfer_container_ownership'
+- add a 'struct_offset' field to virtual function and field blobs
+- add 'dipper' and 'optional' flags to arg blobs
+- add a 'true_stops_emit' flag to signal blobs
+- add variable blob sizes to header
+- store offsets to signature blobs instead of including them directly
+- change the type offset to be measured in words rather than bytes
+
+
+Metadata
+--------
+
+The format of GObject metadata is strongly influenced by the Mozilla XPCOM
+format.
+
+Some of the differences to XPCOM include:
+- Type information is stored not quite as compactly (XPCOM stores it inline
+ in function descriptions in variable-sized blobs of 1 to n bytes. We store
+ 16 bits of type information for each parameter, which is enough to encode
+ simple types inline. Complex (e.g. recursive) types are stored out of line
+ in a separate list of types.
+- String and complex type data is stored outside of interface blobs, references
+ are stored as offsets relative to the start of the metadata. One possibility
+ is to store the strings and types in a pools at the end of the metadata.
+
+Overview
+--------
+
+The metadata has the following general format.
+
+metadata ::= header, directory, blobs, annotations
+
+directory ::= list of entries
+
+entry ::= blob type, name, namespace, offset
+
+blob ::= function|callback|struct|boxed|enum|flags|object|interface|constant|errordomain
+
+annotations ::= list of annotations, sorted by offset
+
+annotation ::= offset, key, value
+
+
+Details
+-------
+
+We describe the fragments that make up the metadata in the form of C structs
+(although some fall short of being valid C structs since they contain multiple
+flexible arrays).
+
+Header (70 bytes)
+
+struct Header
+{
+ gchar[16] magic;
+ guint8 major_version;
+ guint8 minor_version;
+ guint16 reserved;
+
+ guint16 n_entries;
+ guint16 n_local_entries;
+ guint32 directory;
+ guint32 annotations;
+
+ guint32 size;
+ guint32 namespace;
+
+ guint16 entry_blob_size; /* 12 */
+ guint16 function_blob_size; /* 16 */
+ guint16 callback_blob_size; /* 12 */
+ guint16 signal_blob_size; /* 12 */
+ guint16 vfunc_blob_size; /* 16 */
+ guint16 arg_blob_size; /* 12 */
+ guint16 property_blob_size; /* 12 */
+ guint16 field_blob_size; /* 12 */
+ guint16 value_blob_size; /* 16 */
+ guint16 constant_blob_size; /* 20 */
+ guint16 error_domain_blob_size; /* 16 */
+ guint16 annotation_blob_size; /* 12 */
+
+ guint16 signature_blob_size; /* 4 */
+ guint16 enum_blob_size; /* 20 */
+ guint16 struct_blob_size; /* 20 */
+ guint16 object_blob_size; /* 32 */
+ guint16 interface_blob_size; /* 28 */
+}
+
+magic: The string "GOBJ\nMETADATA\r\n\032". This was inspired by XPCOM,
+ which in turn borrowed from PNG.
+
+major_version,
+minor_version:
+ The version of the metadata format. Minor version changes indicate
+ compatible changes and should still allow the metadata to be parsed
+ by a parser designed for the same major_version.
+
+n_entries:
+ The number of entries in the directory.
+
+n_local_entries:
+ The number of entries referring to blobs in this metadata. The
+ local entries must occur before the unresolved entries.
+
+directory:
+ Offset of the directory in the metadata.
+ FIXME: need to specify if and how the directory is sorted
+
+annotations:
+ Offset of the list of annotations in the metadata.
+
+size: The size of the metadata.
+
+namespace:
+ Offset of the namespace string in the metadata.
+
+entry_blob_size:
+function_blob_size:
+callback_blob_size:
+signal_blob_size:
+vfunc_blob_size:
+arg_blob_size:
+property_blob_size:
+field_blob_size:
+value_blob_size:
+annotation_blob_size:
+constant_blob_size:
+ The sizes of fixed-size blobs. Recording this information here
+ allows to write parser which continue to work if the format is
+ extended by adding new fields to the end of the fixed-size blobs.
+
+signature_blob_size:
+enum_blob_size:
+struct_blob_size:
+interface_blob_size:
+ For variable-size blobs, the size of the struct up to the first
+ flexible array member. Recording this information here allows to
+ write parser which continue to work if the format is extended by
+ adding new fields before the first flexible array member in
+ variable-size blobs.
+
+Directory entry (12 bytes)
+
+struct DirectoryEntry
+{
+ guint16 blob_type;
+
+ guint is_local : 1;
+ guint reserved :15;
+
+ guint32 name;
+ guint32 offset;
+}
+
+blob_type:
+ The type of blob this entry points to:
+ 1 function
+ 2 callback
+ 3 struct
+ 4 boxed
+ 5 enum
+ 6 flags
+ 7 object
+ 8 interface
+ 9 constant
+ 10 errordomain
+
+is_local: Wether this entry refers to a blob in this metadata.
+
+name: The name of the entry.
+
+offset: If is_local is set, this is the offset of the blob in the metadata.
+ Otherwise, it is the offset of the namespace in which the blob has
+ to be looked up by name.
+
+
+All blobs pointed to by a directory entry start with the same layout for
+the first 8 bytes (the reserved flags may be used by some interface types)
+
+struct InterfacePrefix
+{
+ guint16 blob_type;
+ guint deprecated : 1;
+ guint reserved :15;
+ guint32 name;
+}
+
+blob_type:
+ An integer specifying the type of the blob, see DirectoryEntry
+ for details.
+
+deprecated:
+ Wether the blob is deprecated.
+
+name: The name of the blob.
+
+
+The SignatureBlob is shared between Functions,
+Callbacks, Signals and VirtualFunctions.
+
+SignatureBlob (8 + 12 * n_arguments bytes)
+
+struct SignatureBlob
+{
+ 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;
+}
+
+
+return_type:
+ Describes the type of the return value. See details below.
+
+may_return_null:
+ Only relevant for pointer types. Indicates whether the caller
+ must expect NULL as a return value.
+
+caller_owns_return_value:
+ If set, the caller is responsible for freeing the return value
+ if it is no longer needed.
+
+caller_owns_return_container:
+ This flag is only relevant if the return type is a container type.
+ If the flag is set, the caller is resonsible for freeing the
+ container, but not its contents.
+
+n_arguments:
+ The number of arguments that this function expects, also the length
+ of the array of ArgBlobs.
+
+arguments:
+ An array of ArgBlob for the arguments of the function.
+
+
+FunctionBlob (16 bytes)
+
+struct FunctionBlob
+{
+ guint16 blob_type; /* 1 */
+
+ guint deprecated : 1;
+ guint is_setter : 1;
+ guint is_getter : 1;
+ guint is_constructor : 1;
+ guint wraps_vfunc : 1;
+ guint reserved : 1;
+ guint index :10;
+
+ guint32 name;
+ guint32 c_name;
+ guint32 signature;
+}
+
+c_name: The symbol which can be used to obtain the function pointer with
+ dlsym().
+
+deprecated
+ The function is deprecated.
+
+is_setter
+ The function is a setter for a property. Language bindings may
+ prefer to not bind individual setters and rely on the generic
+ g_object_set().
+
+is_getter
+ The function is a getter for a property. Language bindings may
+ prefer to not bind individual getters and rely on the generic
+ g_object_get().
+
+is_constructor
+ The function acts as a constructor for the object it is contained
+ in.
+
+wraps_vfunc:
+ The function is a simple wrapper for a virtual function.
+
+index: Index of the property that this function is a setter or getter of
+ in the array of properties of the containing interface, or index
+ of the virtual function that this function wraps.
+
+signature:
+ Offset of the SignatureBlob describing the parameter types and the
+ return value type.
+
+
+CallbackBlob (12 bytes)
+
+struct CallbackBlob
+{
+ guint16 blob_type; /* 2 */
+
+ guint deprecated : 1;
+ guint reserved :15;
+
+ guint32 name;
+ guint32 signature;
+}
+
+signature:
+ Offset of the SignatureBlob describing the parameter types and the
+ return value type.
+
+
+ArgBlob (12 bytes)
+
+struct ArgBlob
+{
+ 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 is_return_value : 1;
+ guint reserved :24:
+
+ SimpleTypeBlob arg_type;
+}
+
+name: A suggested name for the parameter.
+
+in: The parameter is an input to the function
+
+out: The parameter is used to return an output of the function.
+ Parameters can be both in and out. Out parameters implicitly
+ add another level of indirection to the parameter type. Ie if
+ the type is uint32 in an out parameter, the function actually
+ takes an uint32*.
+
+dipper: The parameter is a pointer to a struct or object that will
+ receive an output of the function.
+
+null_ok: Only meaningful for types which are passed as pointers.
+ For an in parameter, indicates if it is ok to pass NULL in, for
+ an out parameter, wether it may return NULL. Note that NULL is a
+ valid GList and GSList value, thus null_ok will normally be set for
+ parameters of these types.
+
+optional:
+ For an out parameter, indicates that NULL may be passed in
+ if the value is not needed.
+
+transfer_ownership:
+ For an in parameter, indicates that the function takes over
+ ownership of the parameter value. For an out parameter, it
+ indicates that the caller is responsible for freeing the return
+ value.
+
+transfer_container_ownership:
+ For container types, indicates that the ownership of the container,
+ but not of its contents is transferred. This is typically the case
+ for out parameters returning lists of statically allocated things.
+
+is_return_value:
+ The parameter should be considered the return value of the function.
+ Only out parameters can be marked as return value, and there can be
+ at most one per function call. If an out parameter is marked as
+ return value, the actual return value of the function should be
+ either void or a boolean indicating the success of the call.
+
+arg_type:
+ Describes the type of the parameter. See details below.
+
+
+Types are specified by two bytes. If the high bytes are zero, the low byte
+describes a basic type, otherwise the 32bit number is an offset which points
+to a TypeBlob.
+
+
+SimpleTypeBlob (4 bytes)
+
+union SimpleTypeBlob
+{
+ struct
+ {
+ guint reserved :24; /* 0 */
+ guint is_pointer : 1;
+ guint reserved : 2;
+ guint tag : 5;
+ };
+ guint32 offset;
+}
+
+is_pointer:
+ indicates wether the type is passed by reference.
+
+tag: specifies what kind of type is described, as follows:
+ 0 void
+ 1 boolean (booleans are passed as ints)
+ 2 int8
+ 3 uint8
+ 4 int16
+ 5 uint16
+ 6 int32
+ 7 uint32
+ 8 int64
+ 9 uint64
+ 10 float
+ 11 double
+ 12 string (these are zero-terminated char* and assumed to be
+ in UTF-8, for other data, use uint8[])
+ 13 GString
+
+ For string and GString, is_pointer will always be set.
+
+offset: Offset relative to header->types that points to a TypeBlob.
+ Unlike other offsets, this is in words (ie 32bit units) rather
+ than bytes.
+
+
+TypeBlob (4 or more bytes)
+
+union TypeBlob
+{
+ ArrayTypeBlob array_type;
+ InterfaceTypeBlob interface_type;
+ ParameterTypeBlob parameter_type;
+ ErrorTypeBlob error_type;
+}
+
+
+ArrayTypeBlob (4 bytes)
+
+Arrays have a tag value of 20. They are passed by reference, thus is_pointer
+is always 1.
+
+struct ArrayTypeBlob
+{
+ guint is_pointer :1; /* 1 */
+ guint reserved :2;
+ guint tag :5; /* 20 */
+ guint zero_terminated :1;
+ guint has_length :1;
+ guint length :6;
+
+ SimpleTypeBlob type;
+}
+
+zero_terminated:
+ Indicates that the array must be terminated by a suitable NULL
+ value.
+
+has_length:
+ Indicates that length points to a parameter specifying the length
+ of the array. If both has_length and zero_terminated are set, the
+ convention is to pass -1 for the length if the array is
+ zero-terminated.
+ FIXME: what does this mean for types of field and properties ?
+
+length: The index of the parameter which is used to pass the length of the
+ array. The parameter must be an integer type and have the same
+ direction as this one.
+
+type: The type of the array elements.
+
+
+InterfaceTypeBlob (4 bytes)
+
+struct InterfaceTypeBlob
+{
+ guint is_pointer :1;
+ guint reserved :2;
+ guint tag :5; /* 21 */
+ guint8 reserved;
+
+ guint16 interface;
+}
+
+Types which are described by an entry in the metadata have a tag value of 21.
+If the interface is an enum of flags type, is_pointer is 0, otherwise it is 1.
+
+interface:
+ Index of the directory entry for the interface.
+
+
+ParameterTypeBlob (4 + n * 4 bytes)
+
+GLists have a tag value of 22, GSLists have a tag value of 23, GHashTables have a
+tag value of 24. They are passed by reference, thus is_pointer is always 1.
+
+struct ParameterTypeBlob
+{
+ guint is_pointer :1; /* 1 */
+ guint reserved :2;
+ guint tag :5; /* 22, 23 or 24 */
+ guint reserved :8;
+
+ guint16 n_types;
+
+ SimpleTypeBlob type[];
+}
+
+n_types: The number of parameter types to follow.
+
+type: Describes the type of the list elements.
+
+
+ErrorTypeBlob (4 + 2 * n_domains bytes)
+
+struct ErrorTypeBlob
+{
+ guint is_pointer :1; /* 1 */
+ guint reserved :2;
+ guint tag :5; /* 25 */
+
+ guint8 reserved;
+
+ guint16 n_domains;
+
+ guint16 domains[];
+}
+
+n_domains:
+ The number of domains to follow
+
+domains: Indices of the directory entries for the error domains
+
+
+ErrorDomainBlob (16 bytes)
+
+struct ErrorDomainBlob
+{
+ guint16 blob_type; /* 10 */
+
+ guint deprecated : 1;
+ guint reserved :15;
+
+ guint32 name;
+
+ guint32 get_quark;
+ guint16 error_codes;
+}
+
+get_quark:
+ The symbol name of the function which must be called to obtain the
+ GQuark for the error domain.
+
+error_codes:
+ Index of the InterfaceBlob describing the enumeration which lists
+ the possible error codes.
+
+
+PropertyBlob (12 bytes)
+
+struct PropertyBlob
+{
+ guint32 name;
+
+ guint deprecated : 1;
+ guint readable : 1;
+ guint writable : 1;
+ guint construct : 1;
+ guint construct_only : 1;
+ guint reserved :27
+
+ SimpleTypeBlob type;
+}
+
+name: The name of the property.
+
+readable:
+writable:
+construct:
+construct_only:
+ The ParamFlags used when registering the property.
+
+type: Describes the type of the property.
+
+
+SignalBlob (12 bytes)
+
+struct SignalBlob
+{
+ guint32 name;
+
+ 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 : 5;
+
+ guint16 class_closure;
+ guint32 signature;
+}
+
+name: The name of the signal.
+
+run_first:
+run_last:
+run_cleanup:
+no_recurse:
+detailed:
+action:
+no_hooks: The flags used when registering the signal.
+
+has_class_closure:
+ Set if the signal has a class closure.
+
+true_stops_emit:
+ Wether the signal has true-stops-emit semantics
+
+class_closure:
+ The index of the class closure in the list of virtual functions
+ of the interface on which the signal is defined.
+
+signature:
+ Offset of the SignatureBlob describing the parameter types and the
+ return value type.
+
+
+VirtualFunctionBlob (16 bytes)
+
+struct VirtualFunctionBlob
+{
+ guint32 name;
+
+ guint must_chain_up : 1;
+ guint must_be_implemented : 1;
+ guint must_not_be_implemented : 1;
+ guint is_class_closure : 1;
+ guint reserved :12;
+
+ guint16 signal;
+ guint16 struct_offset;
+ guint16 reserved;
+ guint32 signature;
+}
+
+name: The name of the virtual function.
+
+must_chain_up:
+ If set, every implementation of this virtual function must
+ chain up to the implementation of the parent class.
+
+must_be_implemented:
+ If set, every derived class must override this virtual function.
+
+must_not_be_implemented:
+ If set, derived class must not override this virtual function.
+
+is_class_closure:
+ Set if this virtual function is the class closure of a signal.
+
+signal:
+ The index of the signal in the list of signals of the interface
+ to which this virtual function belongs.
+
+struct_offset:
+ The offset of the function pointer in the class struct.
+
+signature:
+ Offset of the SignatureBlob describing the parameter types and the
+ return value type.
+
+
+FieldBlob (12 bytes)
+
+struct FieldBlob
+{
+ guint32 name;
+
+ guint readable : 1;
+ guint writable : 1;
+ guint reserved : 6;
+ guint8 bits;
+
+ guint16 struct_offset;
+
+ SimpleTypeBlob type;
+}
+
+name: The name of the field.
+
+readable:
+writable: How the field may be accessed.
+
+bits: If this field is part of a bitfield, the number of bits which it
+ uses, otherwise 0.
+
+struct_offset:
+ The offset of the field in the struct.
+
+type: The type of the field.
+
+
+ValueBlob (16 bytes)
+
+Values commonly occur in enums and flags, but we also allow them to occur
+in interfaces or freestanding, to describe constants.
+
+struct ValueBlob
+{
+ guint deprecated : 1;
+ guint reserved :31;
+ guint32 name;
+
+ guint32 short_name;
+ guint32 value;
+}
+
+short_name:
+ A short name for the value;
+
+value: The numerical value;
+
+
+GTypeBlob (8 bytes)
+
+struct GTypeBlob
+{
+ guint32 gtype_name;
+ guint32 gtype_init;
+}
+
+gtype_name:
+ The name under which the interface is registered with GType.
+
+gtype_init:
+ The symbol name of the get_type() function which registers the type.
+
+
+StructBlob (20 + 8 * n_fields + x * n_functions)
+
+struct StructBlob
+{
+ guint16 blob_type; /* 3: struct, 4: boxed */
+ guint deprecated : 1;
+ guint unregistered : 1;
+ guint reserved :14;
+ guint32 name;
+
+ GTypeBlob gtype;
+
+ guint16 n_fields;
+ guint16 n_functions;
+
+ FieldBlob fields[];
+ FunctionBlob functions[];
+}
+
+unregistered:
+ If this is set, the type is not registered with GType.
+
+gtype: For types which are registered with GType, contains the
+ information about the GType. Otherwise unused.
+
+n_fields:
+n_functions:
+ The lengths of the arrays.
+
+fields: An array of n_fields FieldBlobs.
+
+functions:
+ An array of n_functions FunctionBlobs. The described functions
+ should be considered as methods of the struct.
+
+
+EnumBlob (20 + 16 * n_values)
+
+struct EnumBlob
+{
+ guint16 blob_type; /* 5: enum, 6: flags */
+ guint deprecated : 1;
+ guint unregistered : 1;
+ guint reserved :14;
+ guint32 name;
+
+ GTypeBlob gtype;
+
+ guint16 n_values;
+ guint16 reserved;
+
+ ValueBlob values[];
+}
+
+unregistered:
+ If this is set, the type is not registered with GType.
+
+gtype: For types which are registered with GType, contains the
+ information about the GType. Otherwise unused.
+
+n_values:
+ The lengths of the values arrays.
+
+values: Describes the enum values.
+
+
+ObjectBlob (32 + x bytes)
+
+struct ObjectBlob
+{
+ guint16 blob_type; /* 7 */
+ guint deprecated : 1;
+ guint reserved :15;
+ guint32 name;
+
+ GTypeBlob gtype;
+
+ guint16 parent;
+
+ guint16 n_interfaces;
+ guint16 n_fields;
+ guint16 n_properties;
+ guint16 n_methods;
+ guint16 n_signals;
+ guint16 n_virtual_functions;
+ guint16 n_constants;
+
+ guint16 interfaces[];
+
+ FieldBlob fields[];
+ PropertyBlob properties[];
+ FunctionBlob methods[];
+ SignalBlob signals[];
+ VirtualFunctionBlob virtual_functions[];
+ ConstantBlob constants[];
+}
+
+gtype: Contains the information about the GType.
+
+parent: The directory index of the parent interface. This is only set for
+ objects.
+
+n_interfaces:
+n_fields:
+n_properties:
+n_methods:
+n_signals:
+n_virtual_functions:
+n_constants:
+ The lengths of the arrays.
+
+Up to 16bits of padding may be inserted between the arrays to ensure that they
+start on a 32bit boundary.
+
+interfaces:
+ An array of indices of directory entries for the implemented
+ interfaces.
+
+fields: Describes the fields.
+
+functions:
+ Describes the methods, constructors, setters and getters.
+
+properties:
+ Describes the properties.
+
+signals: Describes the signals.
+
+virtual_functions:
+ Describes the virtual functions.
+
+constants:
+ Describes the constants.
+
+
+InterfaceBlob (28 + x bytes)
+
+struct InterfaceBlob
+{
+ guint16 blob_type; /* 8 */
+ guint deprecated : 1;
+ guint reserved :15;
+ guint32 name;
+
+ GTypeBlob gtype;
+
+ guint16 n_prerequisites;
+ guint16 n_properties;
+ guint16 n_methods;
+ guint16 n_signals;
+ guint16 n_virtual_functions;
+ guint16 n_constants;
+
+ guint16 prerequisites[];
+
+ PropertyBlob properties[];
+ FunctionBlob methods[];
+ SignalBlob signals[];
+ VirtualFunctionBlob virtual_functions[];
+ ConstantBlob constants[];
+}
+
+n_prerequisites:
+n_properties:
+n_methods:
+n_signals:
+n_virtual_functions:
+n_constants:
+ The lengths of the arrays.
+
+Up to 16bits of padding may be inserted between the arrays to ensure that they
+start on a 32bit boundary.
+
+prerequisites:
+ An array of indices of directory entries for required interfaces.
+
+functions:
+ Describes the methods, constructors, setters and getters.
+
+properties:
+ Describes the properties.
+
+signals: Describes the signals.
+
+virtual_functions:
+ Describes the virtual functions.
+
+constants:
+ Describes the constants.
+
+
+ConstantBlob (20 bytes)
+
+struct ConstantBlob
+{
+ guint16 blob_type; /* 9 */
+ guint deprecated : 1;
+ guint reserved :15;
+ guint32 name;
+
+ SimpleTypeBlob type;
+ guint32 size;
+ guint32 offset;
+}
+
+type: The type of the value. In most cases this should be a numeric
+ type or string.
+
+size: The size of the value in bytes.
+
+offset: The offset of the value in the metadata.
+
+
+AnnotationBlob (12 bytes)
+
+struct AnnotationBlob
+{
+ guint32 offset;
+ guint32 name;
+ guint32 value;
+}
+
+offset: The offset of the interface to which this annotation refers.
+ Annotations are kept sorted by offset, so that the annotations
+ of an interface can be found by a binary search.
+
+name: The name of the annotation, a string.
+
+value: The value of the annotation (also a string)
+
+
+
+
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 00000000..fe96a1fc
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,38 @@
+AR=ar
+CC=gcc -g
+CFLAGS=`pkg-config --cflags glib-2.0 gobject-2.0`
+LIBS=`pkg-config --libs glib-2.0 gobject-2.0`
+
+LIBIREPOSITORY_OBJS = \
+ girepository.o \
+ gmetadata.o \
+ ginfo.o
+
+COMPILER_OBJS = \
+ gidlparser.o \
+ gidlmodule.o \
+ gidlnode.o \
+ gmetadata.o \
+ compiler.o
+
+GENERATE_OBJS = generate.o
+
+all: libirepository.so g-idl-generate g-idl-compiler
+
+libirepository.so: $(LIBIREPOSITORY_OBJS)
+ $(CC) -shared -o $@ $(LIBIREPOSITORY_OBJS) $(LIBS)
+
+libirepository.a: $(LIBIREPOSITORY_OBJS)
+ $(AR) csr $@ $(LIBIREPOSITORY_OBJS)
+
+g-idl-generate: $(GENERATE_OBJS) libirepository.a
+ $(CC) -o $@ $(GENERATE_OBJS) $(LIBS) -ldl libirepository.a
+
+g-idl-compiler: $(COMPILER_OBJS)
+ $(CC) -o $@ $(COMPILER_OBJS) $(LIBS) -ldl
+
+.c.o:
+ $(CC) -c $< $(CFLAGS)
+
+clean:
+ rm -rf *.o *~ *.a *.so g-idl-generate g-idl-compiler
diff --git a/src/compiler.c b/src/compiler.c
new file mode 100644
index 00000000..c985d05b
--- /dev/null
+++ b/src/compiler.c
@@ -0,0 +1,214 @@
+/* GObject introspection: Metadata compiler
+ *
+ * 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 <fcntl.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include "gidlmodule.h"
+#include "gidlnode.h"
+#include "gidlparser.h"
+
+gboolean raw = FALSE;
+gboolean no_init = FALSE;
+gchar **input = NULL;
+gchar *output = NULL;
+gchar *mname = NULL;
+
+static gchar *
+format_output (guchar *metadata,
+ gsize len)
+{
+ GString *result;
+ gint i;
+
+ result = g_string_sized_new (6 * len);
+
+ g_string_append_printf (result, "const unsigned char _G_METADATA[] = \n{");
+
+ for (i = 0; i < len; i++)
+ {
+ if (i > 0)
+ g_string_append (result, ", ");
+
+ if (i % 10 == 0)
+ g_string_append (result, "\n\t");
+
+ g_string_append_printf (result, "0x%.2x", metadata[i]);
+ }
+
+ g_string_append_printf (result, "\n};\n\n");
+
+ if (!no_init)
+ {
+ g_string_append_printf (result,
+ "void\n"
+ "register_metadata (void) __attribute__((constructor))\n"
+ "{\n"
+ "\tg_irepository_register (NULL, _G_METADATA);\n"
+ "}\n\n");
+
+ g_string_append_printf (result,
+ "void\n"
+ "unregister_metadata (void) __attribute__((destructor))\n"
+ "{\n"
+ "\tg_irepository_unregister (NULL, _G_METADATA);\n"
+ "}\n");
+ }
+
+ return g_string_free (result, FALSE);
+}
+
+static void
+write_out_metadata (gchar *prefix,
+ gchar *metadata,
+ gsize len)
+{
+ FILE *file;
+
+ if (output == NULL)
+ file = stdout;
+ else
+ {
+ gchar *filename;
+
+ if (prefix)
+ filename = g_strdup_printf ("%s-%s", prefix, output);
+ else
+ filename = g_strdup (output);
+ file = g_fopen (filename, "w");
+
+ if (file == NULL)
+ {
+ g_fprintf (stderr, "failed to open '%s': %s\n",
+ filename, g_strerror (errno));
+ g_free (filename);
+
+ return;
+ }
+
+ g_free (filename);
+ }
+
+ if (raw)
+ fwrite (metadata, 1, len, file);
+ else
+ {
+ gchar *code;
+
+ code = format_output (metadata, len);
+ fputs (code, file);
+ g_free (code);
+ }
+
+ if (output != NULL)
+ fclose (file);
+}
+
+static GOptionEntry options[] =
+{
+ { "raw", 0, 0, G_OPTION_ARG_NONE, &raw, "emit raw metadata", NULL },
+ { "code", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &raw, "emit C code", NULL },
+ { "no-init", 0, 0, G_OPTION_ARG_NONE, &no_init, "do not create _init() function", NULL },
+ { "output", 'o', 0, G_OPTION_ARG_FILENAME, &output, "output file", "FILE" },
+ { "module", 'm', 0, G_OPTION_ARG_STRING, &mname, "module to compile", "NAME" },
+ { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &input, NULL, NULL },
+ { NULL, }
+};
+
+int
+main (int argc, char ** argv)
+{
+ GOptionContext *context;
+ GError *error = NULL;
+ GList *m, *modules;
+ gint i;
+
+ g_metadata_check_sanity ();
+
+ context = g_option_context_new ("");
+ g_option_context_add_main_entries (context, options, NULL);
+ g_option_context_parse (context, &argc, &argv, &error);
+
+ if (!input)
+ {
+ g_fprintf (stderr, "no input files\n");
+
+ return 1;
+ }
+
+ modules = NULL;
+ for (i = 0; input[i]; i++)
+ {
+ GList *mods;
+ mods = g_idl_parse_file (input[i], &error);
+
+ if (mods == NULL)
+ {
+ g_fprintf (stderr, "error parsing file %s: %s\n",
+ input[i], error->message);
+
+ return 1;
+ }
+
+ modules = g_list_concat (modules, mods);
+ }
+
+ for (m = modules; m; m = m->next)
+ {
+ GIdlModule *module = m->data;
+ gchar *prefix;
+ guchar *metadata;
+ gsize len;
+
+ if (mname && strcmp (mname, module->name) != 0)
+ continue;
+
+ g_idl_module_build_metadata (module, modules, &metadata, &len);
+ if (metadata == NULL)
+ {
+ g_error ("failed to build metadata for module '%s'\n", module->name);
+
+ continue;
+ }
+
+ if (!mname && (m->next || m->prev) && output)
+ prefix = module->name;
+ else
+ prefix = NULL;
+
+ write_out_metadata (prefix, metadata, len);
+ g_free (metadata);
+ metadata = NULL;
+
+ /* when writing to stdout, stop after the first module */
+ if (m->next && !output && !mname)
+ {
+ g_warning ("%d modules omitted\n", g_list_length (modules) - 1);
+
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/generate.c b/src/generate.c
new file mode 100644
index 00000000..7d863656
--- /dev/null
+++ b/src/generate.c
@@ -0,0 +1,999 @@
+/* GObject introspection: IDL generator
+ *
+ * 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 <errno.h>
+#include <dlfcn.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gstdio.h>
+
+#include "girepository.h"
+
+gboolean raw = FALSE;
+gchar **input = NULL;
+gchar *output = NULL;
+
+static void
+write_type_info (GITypeInfo *info,
+ FILE *file)
+{
+ gint tag;
+ gint i;
+ GITypeInfo *type;
+
+ const gchar* basic[] = {
+ "void",
+ "gboolean",
+ "gint8",
+ "guint8",
+ "gint16",
+ "guint16",
+ "gint32",
+ "guint32",
+ "gint64",
+ "guint64",
+ "gfloat",
+ "gdouble",
+ "gchar",
+ "GString",
+ "gint",
+ "guint",
+ "glong",
+ "gulong"
+ };
+
+ tag = g_type_info_get_tag (info);
+
+ if (tag < 20)
+ g_print ("%s%s", basic[tag], g_type_info_is_pointer (info) ? "*" : "");
+ else if (tag == 20)
+ {
+ gint length;
+
+ type = g_type_info_get_param_type (info, 0);
+ write_type_info (type, file);
+ g_print ("[");
+
+ length = g_type_info_get_array_length (info);
+
+ if (length >= 0)
+ g_print ("length=%d", length);
+
+ if (g_type_info_is_zero_terminated (info))
+ g_print ("%szero-terminated=1", length >= 0 ? "," : "");
+
+ g_print ("]");
+ g_base_info_unref ((GIBaseInfo *)type);
+ }
+ else if (tag == 21)
+ {
+ GIBaseInfo *iface = g_type_info_get_interface (info);
+ g_print ("%s%s",
+ g_base_info_get_name (iface),
+ g_type_info_is_pointer (info) ? "*" : "");
+ g_base_info_unref (iface);
+ }
+ else if (tag == 22)
+ {
+ type = g_type_info_get_param_type (info, 0);
+ g_print ("GList<");
+ write_type_info (type, file);
+ g_print (">");
+ g_base_info_unref ((GIBaseInfo *)type);
+ }
+ else if (tag == 23)
+ {
+ type = g_type_info_get_param_type (info, 0);
+ g_print ("GSList<");
+ write_type_info (type, file);
+ g_print (">");
+ g_base_info_unref ((GIBaseInfo *)type);
+ }
+ else if (tag == 24)
+ {
+ type = g_type_info_get_param_type (info, 0);
+ g_print ("GHashTable<");
+ write_type_info (type, file);
+ g_base_info_unref ((GIBaseInfo *)type);
+ type = g_type_info_get_param_type (info, 1);
+ g_print(",");
+ write_type_info (type, file);
+ g_print (">");
+ g_base_info_unref ((GIBaseInfo *)type);
+ }
+ else if (tag == 25)
+ {
+ g_print ("GError<");
+ for (i = 0; i < g_type_info_get_n_error_domains (info); i++)
+ {
+ GIErrorDomainInfo *ed = g_type_info_get_error_domain (info, i);
+ g_print ("%s%s", i ? "," : "", g_base_info_get_name ((GIBaseInfo *)ed));
+ g_base_info_unref ((GIBaseInfo *)ed);
+ }
+ g_print (">");
+ }
+}
+
+static void
+write_field_info (GIFieldInfo *info,
+ FILE *file)
+{
+ const gchar *name;
+ GIFieldInfoFlags flags;
+ gint size;
+ gint offset;
+ GITypeInfo *type;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ flags = g_field_info_get_flags (info);
+ size = g_field_info_get_size (info);
+ offset = g_field_info_get_offset (info);
+
+ g_print (" <field cname=\"%s\" readable=\"%s\" writable=\"%s\" ",
+ name,
+ flags & GI_FIELD_IS_READABLE ? "1" : "0",
+ flags & GI_FIELD_IS_WRITABLE ? "1" : "0");
+ if (size)
+ g_print ("bits=\"%d\" ", size);
+ g_print ("offset=\"%d\" ", offset);
+
+ g_print ("type=\"");
+
+ type = g_field_info_get_type (info);
+ write_type_info (type, file);
+ g_base_info_unref ((GIBaseInfo *)type);
+
+ g_print ("\" />\n");
+}
+
+static void
+write_callable_info (GICallableInfo *info,
+ FILE *file,
+ gint indent)
+{
+ GITypeInfo *type;
+ gint i;
+
+ g_fprintf (file, "%*s <return-type type=\"", indent, "");
+
+ type = g_callable_info_get_return_type (info);
+ write_type_info (type, file);
+ g_base_info_unref ((GIBaseInfo *)type);
+
+ g_fprintf (file, "\"/>\n");
+
+ if (g_callable_info_get_n_args (info) > 0)
+ {
+ g_fprintf (file, "%*s <parameters>\n", indent, "");
+ for (i = 0; i < g_callable_info_get_n_args (info); i++)
+ {
+ GIArgInfo *arg = g_callable_info_get_arg (info, i);
+
+ g_fprintf (file, "%*s <parameter name=\"%s\" type=\"",
+ indent, "", g_base_info_get_name ((GIBaseInfo *) arg));
+
+ type = g_arg_info_get_type (arg);
+ write_type_info (type, file);
+ g_base_info_unref ((GIBaseInfo *)type);
+ g_fprintf (file, "\"");
+
+ g_fprintf (file, " direction=\"");
+ switch (g_arg_info_get_direction (arg))
+ {
+ case GI_DIRECTION_IN:
+ g_fprintf (file, "in");
+ break;
+ case GI_DIRECTION_OUT:
+ g_fprintf (file, "out");
+ break;
+ case GI_DIRECTION_INOUT:
+ g_fprintf (file, "inout");
+ break;
+ }
+ g_fprintf (file, "\"");
+
+ if (g_arg_info_may_be_null (arg))
+ g_fprintf (file, " null-ok=\"1\"");
+
+ if (g_arg_info_is_dipper (arg))
+ g_fprintf (file, " dipper=\"1\"");
+
+ if (g_arg_info_is_return_value (arg))
+ g_fprintf (file, " retval=\"1\"");
+
+ if (g_arg_info_is_optional (arg))
+ g_fprintf (file, " optional=\"1\"");
+
+ g_fprintf (file, "/>\n");
+
+ g_base_info_unref ((GIBaseInfo *)arg);
+ }
+
+ g_fprintf (file, "%*s </parameters>\n", indent, "");
+ }
+}
+
+static void
+write_function_info (GIFunctionInfo *info,
+ FILE *file,
+ gint indent)
+{
+ GIFunctionInfoFlags flags;
+ const gchar *tag;
+ const gchar *name;
+ const gchar *cname;
+ gboolean deprecated;
+
+ flags = g_function_info_get_flags (info);
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ cname = g_function_info_get_symbol (info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ if (flags & GI_FUNCTION_IS_CONSTRUCTOR)
+ tag = "constructor";
+ else if (flags & GI_FUNCTION_IS_METHOD)
+ tag = "method";
+ else
+ tag = "function";
+
+ g_fprintf (file, "%*s<%s name=\"%s\" cname=\"%s\"",
+ indent, "", tag, name, cname);
+
+ if (flags & GI_FUNCTION_IS_SETTER)
+ g_fprintf (file, " type=\"setter\"");
+ else if (flags & GI_FUNCTION_IS_GETTER)
+ g_fprintf (file, " type=\"getter\"");
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ g_fprintf (file, ">\n");
+ write_callable_info ((GICallableInfo*)info, file, indent);
+ g_fprintf (file, "%*s</%s>\n", indent, "", tag);
+}
+
+static void
+write_callback_info (GICallbackInfo *info,
+ FILE *file,
+ gint indent)
+{
+ GIFunctionInfoFlags flags;
+ const gchar *name;
+ gboolean deprecated;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ g_fprintf (file, "%*s<callback name=\"%s\"", indent, "", name);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ g_fprintf (file, ">\n");
+ write_callable_info ((GICallableInfo*)info, file, indent);
+ g_fprintf (file, "%*s</callback>\n", indent, "");
+}
+
+static void
+write_struct_info (GIStructInfo *info,
+ FILE *file)
+{
+ const gchar *name;
+ const gchar *type_name;
+ const gchar *type_init;
+ gboolean deprecated;
+ gint i;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_BOXED)
+ {
+ type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
+ type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
+
+ g_fprintf (file, " <boxed name=\"%s\" cname=\"%s\" get-type=\"%s\"", name, type_name, type_init);
+ }
+ else
+ g_fprintf (file, " <struct name=\"%s\" cname=\"%s\"", name);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ g_fprintf (file, ">\n");
+
+ for (i = 0; i < g_struct_info_get_n_fields (info); i++)
+ {
+ GIFieldInfo *field = g_struct_info_get_field (info, i);
+ write_field_info (field, file);
+ g_base_info_unref ((GIBaseInfo *)field);
+ }
+
+ for (i = 0; i < g_struct_info_get_n_methods (info); i++)
+ {
+ GIFunctionInfo *function = g_struct_info_get_method (info, i);
+ write_function_info (function, file, 6);
+ g_base_info_unref ((GIBaseInfo *)function);
+ }
+
+ if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_BOXED)
+ g_fprintf (file, " </boxed>\n");
+ else
+ g_fprintf (file, " </struct>\n");
+}
+
+static void
+write_value_info (GIValueInfo *info,
+ FILE *file)
+{
+ const gchar *name;
+ const gchar *short_name;
+ glong value;
+ gboolean deprecated;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ short_name = g_value_info_get_short_name (info);
+ value = g_value_info_get_value (info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ g_print (" <member name=\"%s\" cname=\"%s\" value=\"%d\" ",
+ name, short_name, value);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ g_print (" />\n");
+}
+
+static void
+write_constant_info (GIConstantInfo *info,
+ FILE *file,
+ gint indent)
+{
+ GITypeInfo *type;
+ const gchar *name;
+ gboolean deprecated;
+ GArgument value;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ g_print ("%*s<constant name=\"%s\" type=\"", indent, "", name);
+
+ type = g_constant_info_get_type (info);
+ write_type_info (type, file);
+ g_fprintf (file, "\" value=\"");
+
+ g_constant_info_get_value (info, &value);
+ switch (g_type_info_get_tag (type))
+ {
+ case GI_TYPE_TAG_BOOLEAN:
+ g_fprintf (file, "%d", value.v_boolean);
+ break;
+ case GI_TYPE_TAG_INT8:
+ g_fprintf (file, "%d", value.v_int8);
+ break;
+ case GI_TYPE_TAG_UINT8:
+ g_fprintf (file, "%d", value.v_uint8);
+ break;
+ case GI_TYPE_TAG_INT16:
+ g_fprintf (file, "%" G_GINT16_FORMAT, value.v_int16);
+ break;
+ case GI_TYPE_TAG_UINT16:
+ g_fprintf (file, "%" G_GUINT16_FORMAT, value.v_uint16);
+ break;
+ case GI_TYPE_TAG_INT32:
+ g_fprintf (file, "%" G_GINT32_FORMAT, value.v_int32);
+ break;
+ case GI_TYPE_TAG_UINT32:
+ g_fprintf (file, "%" G_GUINT32_FORMAT, value.v_uint32);
+ break;
+ case GI_TYPE_TAG_INT64:
+ g_fprintf (file, "%" G_GINT64_FORMAT, value.v_int64);
+ break;
+ case GI_TYPE_TAG_UINT64:
+ g_fprintf (file, "%" G_GUINT64_FORMAT, value.v_uint64);
+ break;
+ case GI_TYPE_TAG_FLOAT:
+ g_fprintf (file, "%f", value.v_float);
+ break;
+ case GI_TYPE_TAG_DOUBLE:
+ g_fprintf (file, "%Lf", value.v_double);
+ break;
+ case GI_TYPE_TAG_STRING:
+ g_fprintf (file, "%s", value.v_string);
+ break;
+ case GI_TYPE_TAG_INT:
+ g_fprintf (file, "%d", value.v_int);
+ break;
+ case GI_TYPE_TAG_UINT:
+ g_fprintf (file, "%d", value.v_uint);
+ break;
+ case GI_TYPE_TAG_LONG:
+ g_fprintf (file, "%ld", value.v_long);
+ break;
+ case GI_TYPE_TAG_ULONG:
+ g_fprintf (file, "%ld", value.v_ulong);
+ break;
+ }
+ g_fprintf (file, "\" />\n");
+
+ g_base_info_unref ((GIBaseInfo *)type);
+}
+
+
+static void
+write_enum_info (GIEnumInfo *info,
+ FILE *file)
+{
+ const gchar *name;
+ const gchar *type_name;
+ const gchar *type_init;
+ gboolean deprecated;
+ gint i;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
+ type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
+
+ if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_ENUM)
+ g_fprintf (file, " <enum ");
+ else
+ g_fprintf (file, " <flags ");
+ g_fprintf (file, "name=\"%s\" cname=\"%s\"", name, type_name, type_init);
+
+ if (type_init)
+ g_fprintf (file, " get-type=\"%s\"", type_init);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ g_fprintf (file, ">\n");
+
+ for (i = 0; i < g_enum_info_get_n_values (info); i++)
+ {
+ GIValueInfo *value = g_enum_info_get_value (info, i);
+ write_value_info (value, file);
+ g_base_info_unref ((GIBaseInfo *)value);
+ }
+
+ if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_ENUM)
+ g_fprintf (file, " </enum>\n");
+ else
+ g_fprintf (file, " </flags>\n");
+}
+
+static void
+write_signal_info (GISignalInfo *info,
+ FILE *file)
+{
+ GSignalFlags flags;
+ const gchar *name;
+ gboolean deprecated;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ flags = g_signal_info_get_flags (info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ g_fprintf (file, " <signal name=\"%s\"", name);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ if (flags & G_SIGNAL_RUN_FIRST)
+ g_fprintf (file, " when=\"FIRST\"");
+ else if (flags & G_SIGNAL_RUN_LAST)
+ g_fprintf (file, " when=\"LAST\"");
+ else if (flags & G_SIGNAL_RUN_CLEANUP)
+ g_fprintf (file, " when=\"CLEANUP\"");
+
+ if (flags & G_SIGNAL_NO_RECURSE)
+ g_fprintf (file, " no-recurse=\"1\"");
+
+ if (flags & G_SIGNAL_DETAILED)
+ g_fprintf (file, " detailed=\"1\"");
+
+ if (flags & G_SIGNAL_ACTION)
+ g_fprintf (file, " action=\"1\"");
+
+ if (flags & G_SIGNAL_NO_HOOKS)
+ g_fprintf (file, " no-hooks=\"1\"");
+
+ g_fprintf (file, ">\n");
+
+ write_callable_info ((GICallableInfo*)info, file, 6);
+ g_fprintf (file, " </signal>\n");
+}
+
+static void
+write_vfunc_info (GIVFuncInfo *info,
+ FILE *file)
+{
+ GIVFuncInfoFlags flags;
+ const gchar *name;
+ gboolean deprecated;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ flags = g_vfunc_info_get_flags (info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ g_fprintf (file, " <vfunc name=\"%s\"", name);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ if (flags & GI_VFUNC_MUST_CHAIN_UP)
+ g_fprintf (file, " must-chain-up=\"1\"");
+
+ if (flags & GI_VFUNC_MUST_OVERRIDE)
+ g_fprintf (file, " override=\"always\"");
+ else if (flags & GI_VFUNC_MUST_NOT_OVERRIDE)
+ g_fprintf (file, " override=\"never\"");
+
+ g_fprintf (file, ">\n");
+
+ write_callable_info ((GICallableInfo*)info, file, 6);
+ g_fprintf (file, " </vfunc>\n");
+}
+
+static void
+write_property_info (GIPropertyInfo *info,
+ FILE *file)
+{
+ GParamFlags flags;
+ const gchar *name;
+ gboolean deprecated;
+ GITypeInfo *type;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ flags = g_property_info_get_flags (info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ g_fprintf (file, " <property name=\"%s\"", name);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ if (flags & G_PARAM_READABLE)
+ g_fprintf (file, " readable=\"1\"");
+ else
+ g_fprintf (file, " readable=\"0\"");
+
+ if (flags & G_PARAM_WRITABLE)
+ g_fprintf (file, " writable=\"1\"");
+ else
+ g_fprintf (file, " writable=\"0\"");
+
+ if (flags & G_PARAM_CONSTRUCT)
+ g_fprintf (file, " construct=\"1\"");
+
+ if (flags & G_PARAM_CONSTRUCT_ONLY)
+ g_fprintf (file, " construct-only=\"1\"");
+
+ type = g_property_info_get_type (info);
+ g_fprintf (file, " type=\"");
+ write_type_info (type, file);
+ g_fprintf (file, "\"");
+
+ g_fprintf (file, "/>\n");
+}
+
+static void
+write_object_info (GIObjectInfo *info,
+ FILE *file)
+{
+ const gchar *name;
+ const gchar *parent;
+ const gchar *type_name;
+ const gchar *type_init;
+ gboolean deprecated;
+ GIObjectInfo *pnode;
+ gint i;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ pnode = g_object_info_get_parent (info);
+ if (pnode)
+ parent = g_base_info_get_name ((GIBaseInfo *)pnode);
+ else
+ parent = NULL;
+ g_base_info_unref ((GIBaseInfo *)pnode);
+
+ type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
+ type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
+ g_fprintf (file, " <object name=\"%s\"", name);
+
+ if (parent)
+ g_fprintf (file, " parent=\"%s\"", parent);
+
+ g_fprintf (file, " cname=\"%s\" get-type=\"%s\"", type_name, type_init);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ g_fprintf (file, ">\n");
+
+ if (g_object_info_get_n_interfaces (info) > 0)
+ {
+ g_fprintf (file, " <implements>\n");
+ for (i = 0; i < g_object_info_get_n_interfaces (info); i++)
+ {
+ GIInterfaceInfo *imp = g_object_info_get_interface (info, i);
+ g_fprintf (file, " <interface name=\"%s\" />\n",
+ g_base_info_get_name ((GIBaseInfo*)imp));
+ g_base_info_unref ((GIBaseInfo*)imp);
+ }
+ g_fprintf (file, " </implements>\n");
+ }
+
+ for (i = 0; i < g_object_info_get_n_fields (info); i++)
+ {
+ GIFieldInfo *field = g_object_info_get_field (info, i);
+ write_field_info (field, file);
+ g_base_info_unref ((GIBaseInfo *)field);
+ }
+
+ for (i = 0; i < g_object_info_get_n_methods (info); i++)
+ {
+ GIFunctionInfo *function = g_object_info_get_method (info, i);
+ write_function_info (function, file, 6);
+ g_base_info_unref ((GIBaseInfo *)function);
+ }
+
+ for (i = 0; i < g_object_info_get_n_properties (info); i++)
+ {
+ GIPropertyInfo *prop = g_object_info_get_property (info, i);
+ write_property_info (prop, file);
+ g_base_info_unref ((GIBaseInfo *)prop);
+ }
+
+ for (i = 0; i < g_object_info_get_n_signals (info); i++)
+ {
+ GISignalInfo *signal = g_object_info_get_signal (info, i);
+ write_signal_info (signal, file);
+ g_base_info_unref ((GIBaseInfo *)signal);
+ }
+
+ for (i = 0; i < g_object_info_get_n_vfuncs (info); i++)
+ {
+ GIVFuncInfo *vfunc = g_object_info_get_vfunc (info, i);
+ write_vfunc_info (vfunc, file);
+ g_base_info_unref ((GIBaseInfo *)vfunc);
+ }
+
+ for (i = 0; i < g_object_info_get_n_constants (info); i++)
+ {
+ GIConstantInfo *constant = g_object_info_get_constant (info, i);
+ write_constant_info (constant, file, 6);
+ g_base_info_unref ((GIBaseInfo *)constant);
+ }
+
+ g_fprintf (file, " </object>\n");
+}
+
+static void
+write_interface_info (GIInterfaceInfo *info,
+ FILE *file)
+{
+ const gchar *name;
+ const gchar *type_name;
+ const gchar *type_init;
+ gboolean deprecated;
+ gint i;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+ type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
+ type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
+ g_fprintf (file, " <interface name=\"%s\" cname=\"%s\" get-type=\"%s\"",
+ name, type_name, type_init);
+
+ if (deprecated)
+ g_fprintf (file, " deprecated=\"1\"");
+
+ g_fprintf (file, ">\n");
+
+ if (g_interface_info_get_n_prerequisites (info) > 0)
+ {
+ g_fprintf (file, " <requires>\n");
+ for (i = 0; i < g_interface_info_get_n_prerequisites (info); i++)
+ {
+ GIBaseInfo *req = g_interface_info_get_prerequisite (info, i);
+
+ if (g_base_info_get_type (req) == GI_INFO_TYPE_INTERFACE)
+ g_fprintf (file, " <interface name=\"%s\" />\n",
+ g_base_info_get_name (req));
+ else
+ g_fprintf (file, " <object name=\"%s\" />\n",
+ g_base_info_get_name (req));
+
+ g_base_info_unref (req);
+ }
+ g_fprintf (file, " </requires>\n");
+ }
+
+ for (i = 0; i < g_interface_info_get_n_methods (info); i++)
+ {
+ GIFunctionInfo *function = g_interface_info_get_method (info, i);
+ write_function_info (function, file, 6);
+ g_base_info_unref ((GIBaseInfo *)function);
+ }
+
+ for (i = 0; i < g_interface_info_get_n_properties (info); i++)
+ {
+ GIPropertyInfo *prop = g_interface_info_get_property (info, i);
+ write_property_info (prop, file);
+ g_base_info_unref ((GIBaseInfo *)prop);
+ }
+
+ for (i = 0; i < g_interface_info_get_n_signals (info); i++)
+ {
+ GISignalInfo *signal = g_interface_info_get_signal (info, i);
+ write_signal_info (signal, file);
+ g_base_info_unref ((GIBaseInfo *)signal);
+ }
+
+ for (i = 0; i < g_interface_info_get_n_vfuncs (info); i++)
+ {
+ GIVFuncInfo *vfunc = g_interface_info_get_vfunc (info, i);
+ write_vfunc_info (vfunc, file);
+ g_base_info_unref ((GIBaseInfo *)vfunc);
+ }
+
+ for (i = 0; i < g_interface_info_get_n_constants (info); i++)
+ {
+ GIConstantInfo *constant = g_interface_info_get_constant (info, i);
+ write_constant_info (constant, file, 6);
+ g_base_info_unref ((GIBaseInfo *)constant);
+ }
+
+ g_fprintf (file, " </interface>\n");
+}
+
+static void
+write_error_domain_info (GIErrorDomainInfo *info,
+ FILE *file)
+{
+ GIBaseInfo *enum_;
+ const gchar *name, *quark, *codes;
+
+ name = g_base_info_get_name ((GIBaseInfo *)info);
+ quark = g_error_domain_info_get_quark (info);
+ enum_ = (GIBaseInfo *)g_error_domain_info_get_codes (info);
+ codes = g_base_info_get_name (enum_);
+ g_base_info_unref (enum_);
+
+ g_fprintf (file,
+ " <errordomain name=\"%s\" get-quark=\"%s\" codes=\"%s\" />\n",
+ name, quark, codes);
+}
+
+static void
+write_repository (GIRepository *repository,
+ gboolean needs_prefix)
+{
+ FILE *file;
+ gchar **namespaces;
+ gint i, j;
+
+ namespaces = g_irepository_get_namespaces (repository);
+
+ if (output == NULL)
+ file = stdout;
+ else
+ {
+ gchar *filename;
+
+ if (needs_prefix)
+ filename = g_strdup_printf ("%s-%s", namespaces[0], output);
+ else
+ filename = g_strdup (output);
+ file = g_fopen (filename, "w");
+
+ if (file == NULL)
+ {
+ g_fprintf (stderr, "failed to open '%s': %s\n",
+ filename, g_strerror (errno));
+ g_free (filename);
+
+ return;
+ }
+
+ g_free (filename);
+ }
+
+ g_fprintf (file, "<?xml version=\"1.0\"?>\n");
+ g_fprintf (file, "<api version=\"1.0\">\n");
+
+ for (i = 0; namespaces[i]; i++)
+ {
+ g_fprintf (file, " <namespace name=\"%s\">\n", namespaces[i]);
+
+ for (j = 0; j < g_irepository_get_n_infos (repository, namespaces[i]); j++)
+ {
+ GIBaseInfo *info = g_irepository_get_info (repository, namespaces[i], j);
+ switch (g_base_info_get_type (info))
+ {
+ case GI_INFO_TYPE_FUNCTION:
+ write_function_info ((GIFunctionInfo *)info, file, 4);
+ break;
+
+ case GI_INFO_TYPE_CALLBACK:
+ write_callback_info ((GICallbackInfo *)info, file, 4);
+ break;
+
+ case GI_INFO_TYPE_STRUCT:
+ case GI_INFO_TYPE_BOXED:
+ write_struct_info ((GIStructInfo *)info, file);
+ break;
+
+ case GI_INFO_TYPE_ENUM:
+ case GI_INFO_TYPE_FLAGS:
+ write_enum_info ((GIEnumInfo *)info, file);
+ break;
+
+ case GI_INFO_TYPE_CONSTANT:
+ write_constant_info ((GIConstantInfo *)info, file, 4);
+ break;
+
+ case GI_INFO_TYPE_OBJECT:
+ write_object_info ((GIObjectInfo *)info, file);
+ break;
+
+ case GI_INFO_TYPE_INTERFACE:
+ write_interface_info ((GIInterfaceInfo *)info, file);
+ break;
+
+ case GI_INFO_TYPE_ERROR_DOMAIN:
+ write_error_domain_info ((GIErrorDomainInfo *)info, file);
+ break;
+ }
+
+ g_base_info_unref (info);
+ }
+
+ g_fprintf (file, " </namespace>\n");
+ }
+
+ g_fprintf (file, "</api>\n");
+
+ if (output != NULL)
+ fclose (file);
+
+ g_strfreev (namespaces);
+}
+
+static GOptionEntry options[] =
+{
+ { "raw", 0, 0, G_OPTION_ARG_NONE, &raw, "handle raw metadata", NULL },
+ { "output", 'o', 0, G_OPTION_ARG_FILENAME, &output, "output file", "FILE" },
+ { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &input, NULL, NULL },
+ { NULL, }
+};
+
+static const guchar *
+load_metadata (const gchar *filename,
+ void **dlhandle)
+{
+ guchar *metadata;
+ void *handle;
+ char *error;
+
+ handle = dlopen (filename, RTLD_LAZY);
+ metadata = dlsym (handle, "_G_METADATA");
+
+ error = dlerror ();
+
+ if (dlhandle)
+ *dlhandle = handle;
+
+ if (error)
+ {
+ g_fprintf (stderr,
+ "Could not load metadata from '%s': %s\n",
+ filename, error);
+
+ return NULL;
+ }
+
+ return metadata;
+}
+
+int
+main (int argc, char *argv[])
+{
+ GOptionContext *context;
+ GError *error = NULL;
+ gboolean needs_prefix;
+ gint i;
+
+ g_type_init ();
+
+ g_metadata_check_sanity ();
+
+ context = g_option_context_new ("");
+ g_option_context_add_main_entries (context, options, NULL);
+ g_option_context_parse (context, &argc, &argv, &error);
+
+ if (!input)
+ {
+ g_fprintf (stderr, "no input files\n");
+
+ return 1;
+ }
+
+ for (i = 0; input[i]; i++)
+ {
+ void *dlhandle = NULL;
+ const guchar *metadata;
+
+ if (raw)
+ {
+ if (!g_file_get_contents (input[i], (gchar **)&metadata, NULL, &error))
+ {
+ g_fprintf (stderr, "failed to read '%s': %s\n",
+ input[i], error->message);
+ g_clear_error (&error);
+ continue;
+ }
+ }
+ else
+ {
+ metadata = load_metadata (input[i], &dlhandle);
+ if (!metadata)
+ {
+ g_fprintf (stderr, "failed to load metadata from '%s'\n",
+ input[i]);
+ continue;
+ }
+ }
+
+ if (input[i + 1] && output)
+ needs_prefix = TRUE;
+ else
+ needs_prefix = FALSE;
+
+ g_irepository_register (g_irepository_get_default (), metadata);
+ write_repository (g_irepository_get_default (), needs_prefix);
+ g_irepository_unregister (g_irepository_get_default (), metadata);
+
+ if (dlhandle)
+ {
+ dlclose (dlhandle);
+ dlhandle = NULL;
+ }
+
+ /* when writing to stdout, stop after the first module */
+ if (input[i + 1] && !output)
+ {
+ g_fprintf (stderr, "warning, %d modules omitted\n",
+ g_strv_length (input) - 1);
+
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/gidlmodule.c b/src/gidlmodule.c
new file mode 100644
index 00000000..7d0a9c6a
--- /dev/null
+++ b/src/gidlmodule.c
@@ -0,0 +1,187 @@
+/* GObject introspection: Metadata creation
+ *
+ * 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 <stdio.h>
+
+#include "gidlmodule.h"
+#include "gidlnode.h"
+#include "gmetadata.h"
+
+#define ALIGN_VALUE(this, boundary) \
+ (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
+
+
+GIdlModule *
+g_idl_module_new (const gchar *name)
+{
+ GIdlModule *module;
+
+ module = g_new (GIdlModule, 1);
+
+ module->name = g_strdup (name);
+ module->entries = NULL;
+
+ return module;
+}
+
+void
+g_idl_module_free (GIdlModule *module)
+{
+ GList *e;
+
+ g_free (module->name);
+
+ for (e = module->entries; e; e = e->next)
+ g_idl_node_free ((GIdlNode *)e->data);
+
+ g_list_free (module->entries);
+
+ g_free (module);
+}
+
+void
+g_idl_module_build_metadata (GIdlModule *module,
+ GList *modules,
+ guchar **metadata,
+ gsize *length)
+{
+ gint i;
+ GList *e;
+ Header *header;
+ DirEntry *entry;
+ guint32 header_size;
+ guint32 dir_size;
+ guint32 n_entries;
+ guint32 n_local_entries;
+ guint32 size, offset, offset2;
+ GHashTable *strings;
+ GHashTable *types;
+ guchar *data;
+
+ header_size = ALIGN_VALUE (sizeof (Header), 4);
+ n_local_entries = g_list_length (module->entries);
+
+ restart:
+ strings = g_hash_table_new (g_str_hash, g_str_equal);
+ types = g_hash_table_new (g_str_hash, g_str_equal);
+ n_entries = g_list_length (module->entries);
+
+ g_fprintf (stderr, "%d entries (%d local)\n", n_entries, n_local_entries);
+
+ dir_size = n_entries * 12;
+ size = header_size + dir_size;
+
+ for (e = module->entries; e; e = e->next)
+ {
+ GIdlNode *node = e->data;
+
+ size += g_idl_node_get_full_size (node);
+ }
+
+ data = g_malloc (size);
+
+ /* fill in header */
+ header = (Header *)data;
+ memcpy (header, G_IDL_MAGIC, 16);
+ header->major_version = 1;
+ header->minor_version = 0;
+ 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->size = 0; /* filled in later */
+ header->namespace = write_string (module->name, strings, data, &header_size);
+ header->directory = ALIGN_VALUE (header_size, 4);
+ 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 = 16;
+ 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;
+
+ /* fill in directory and content */
+ entry = (DirEntry *)&data[header->directory];
+
+ offset2 = header->directory + dir_size;
+
+ for (e = module->entries, i = 0; e; e = e->next, i++)
+ {
+ GIdlNode *node = e->data;
+
+ /* we picked up implicit xref nodes, start over */
+ if (i == n_entries)
+ {
+ g_fprintf (stderr, "Found implicit cross references, starting over\n");
+ g_hash_table_destroy (strings);
+ g_hash_table_destroy (types);
+ strings = NULL;
+
+ g_free (data);
+ data = NULL;
+
+ goto restart;
+ }
+
+ offset = offset2;
+
+ if (node->type == G_IDL_NODE_XREF)
+ {
+ entry->blob_type = 0;
+ entry->local = FALSE;
+ entry->offset = write_string (((GIdlNodeXRef*)node)->namespace, strings, data, &offset2);
+ entry->name = write_string (node->name, strings, data, &offset2);
+ }
+ else
+ {
+ offset2 = offset + g_idl_node_get_size (node);
+
+ entry->blob_type = node->type;
+ entry->local = TRUE;
+ entry->offset = offset;
+ entry->name = write_string (node->name, strings, data, &offset2);
+
+ g_idl_node_build_metadata (node, module, modules,
+ strings, types, data, &offset, &offset2);
+ }
+
+ entry++;
+ }
+
+ g_hash_table_destroy (strings);
+ g_hash_table_destroy (types);
+
+ header->annotations = offset2;
+
+ *metadata = g_realloc (data, offset2);
+ *length = header->size = offset2;
+}
+
diff --git a/src/gidlmodule.h b/src/gidlmodule.h
new file mode 100644
index 00000000..17135764
--- /dev/null
+++ b/src/gidlmodule.h
@@ -0,0 +1,47 @@
+/* GObject introspection: Parsed IDL
+ *
+ * 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_IDL_MODULE_H__
+#define __G_IDL_MODULE_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _GIdlModule GIdlModule;
+
+struct _GIdlModule
+{
+ gchar *name;
+ GList *entries;
+};
+
+GIdlModule *g_idl_module_new (const gchar *name);
+void g_idl_module_free (GIdlModule *module);
+
+void g_idl_module_build_metadata (GIdlModule *module,
+ GList *modules,
+ guchar **metadata,
+ gsize *length);
+
+G_END_DECLS
+
+#endif /* __G_IDL_MODULE_H__ */
diff --git a/src/gidlnode.c b/src/gidlnode.c
new file mode 100644
index 00000000..6dea7087
--- /dev/null
+++ b/src/gidlnode.c
@@ -0,0 +1,1749 @@
+/* GObject introspection: Metadata creation
+ *
+ * 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 <stdio.h>
+
+#include "gidlmodule.h"
+#include "gidlnode.h"
+#include "gmetadata.h"
+
+#define ALIGN_VALUE(this, boundary) \
+ (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
+
+
+GIdlNode *
+g_idl_node_new (GIdlNodeTypeId type)
+{
+ GIdlNode *node = NULL;
+
+ switch (type)
+ {
+ case G_IDL_NODE_FUNCTION:
+ node = g_malloc0 (sizeof (GIdlNodeFunction));
+ break;
+
+ case G_IDL_NODE_PARAM:
+ node = g_malloc0 (sizeof (GIdlNodeParam));
+ break;
+
+ case G_IDL_NODE_TYPE:
+ node = g_malloc0 (sizeof (GIdlNodeType));
+ break;
+
+ case G_IDL_NODE_OBJECT:
+ case G_IDL_NODE_INTERFACE:
+ node = g_malloc0 (sizeof (GIdlNodeInterface));
+ break;
+
+ case G_IDL_NODE_SIGNAL:
+ node = g_malloc0 (sizeof (GIdlNodeSignal));
+ break;
+
+ case G_IDL_NODE_PROPERTY:
+ node = g_malloc0 (sizeof (GIdlNodeProperty));
+ break;
+
+ case G_IDL_NODE_VFUNC:
+ node = g_malloc0 (sizeof (GIdlNodeFunction));
+ break;
+
+ case G_IDL_NODE_FIELD:
+ node = g_malloc0 (sizeof (GIdlNodeField));
+ break;
+
+ case G_IDL_NODE_ENUM:
+ case G_IDL_NODE_FLAGS:
+ node = g_malloc0 (sizeof (GIdlNodeEnum));
+ break;
+
+ case G_IDL_NODE_BOXED:
+ node = g_malloc0 (sizeof (GIdlNodeBoxed));
+ break;
+
+ case G_IDL_NODE_STRUCT:
+ node = g_malloc0 (sizeof (GIdlNodeStruct));
+ break;
+
+ case G_IDL_NODE_VALUE:
+ node = g_malloc0 (sizeof (GIdlNodeValue));
+ break;
+
+ case G_IDL_NODE_CONSTANT:
+ node = g_malloc0 (sizeof (GIdlNodeConstant));
+ break;
+
+ case G_IDL_NODE_ERROR_DOMAIN:
+ node = g_malloc0 (sizeof (GIdlNodeErrorDomain));
+ break;
+
+ case G_IDL_NODE_XREF:
+ node = g_malloc0 (sizeof (GIdlNodeXRef));
+ break;
+
+ default:
+ g_error ("Unhandled node type %d\n", type);
+ break;
+ }
+
+ node->type = type;
+
+ return node;
+}
+
+void
+g_idl_node_free (GIdlNode *node)
+{
+ GList *l;
+
+ switch (node->type)
+ {
+ case G_IDL_NODE_FUNCTION:
+ {
+ GIdlNodeFunction *function = (GIdlNodeFunction *)node;
+
+ g_free (node->name);
+ g_free (function->c_name);
+ g_idl_node_free ((GIdlNode *)function->result);
+ for (l = function->parameters; l; l = l->next)
+ g_idl_node_free ((GIdlNode *)l->data);
+ g_list_free (function->parameters);
+ }
+ break;
+
+ case G_IDL_NODE_TYPE:
+ {
+ GIdlNodeType *type = (GIdlNodeType *)node;
+
+ g_free (node->name);
+ if (type->parameter_type1)
+ g_idl_node_free ((GIdlNode *)type->parameter_type1);
+ if (type->parameter_type2)
+ g_idl_node_free ((GIdlNode *)type->parameter_type2);
+
+ g_free (type->interface);
+ g_strfreev (type->errors);
+
+ }
+ break;
+
+ case G_IDL_NODE_PARAM:
+ {
+ GIdlNodeParam *param = (GIdlNodeParam *)node;
+
+ g_free (node->name);
+ g_idl_node_free ((GIdlNode *)param->type);
+ }
+ break;
+
+ case G_IDL_NODE_PROPERTY:
+ {
+ GIdlNodeProperty *property = (GIdlNodeProperty *)node;
+
+ g_free (node->name);
+ g_idl_node_free ((GIdlNode *)property->type);
+ }
+ break;
+
+ case G_IDL_NODE_SIGNAL:
+ {
+ GIdlNodeSignal *signal = (GIdlNodeSignal *)node;
+
+ g_free (node->name);
+ for (l = signal->parameters; l; l = l->next)
+ g_idl_node_free ((GIdlNode *)l->data);
+ g_list_free (signal->parameters);
+ g_idl_node_free ((GIdlNode *)signal->result);
+ }
+ break;
+
+ case G_IDL_NODE_VFUNC:
+ {
+ GIdlNodeVFunc *vfunc = (GIdlNodeVFunc *)node;
+
+ g_free (node->name);
+ for (l = vfunc->parameters; l; l = l->next)
+ g_idl_node_free ((GIdlNode *)l->data);
+ g_list_free (vfunc->parameters);
+ g_idl_node_free ((GIdlNode *)vfunc->result);
+ }
+ break;
+
+ case G_IDL_NODE_FIELD:
+ {
+ GIdlNodeField *field = (GIdlNodeField *)node;
+
+ g_free (node->name);
+ g_free (field->c_name);
+ g_idl_node_free ((GIdlNode *)field->type);
+ }
+ break;
+
+ case G_IDL_NODE_OBJECT:
+ case G_IDL_NODE_INTERFACE:
+ {
+ GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
+
+ g_free (node->name);
+ g_free (iface->c_name);
+ g_free (iface->init_func);
+
+ g_free (iface->parent);
+
+ for (l = iface->interfaces; l; l = l->next)
+ g_free ((GIdlNode *)l->data);
+ g_list_free (iface->interfaces);
+
+ for (l = iface->members; l; l = l->next)
+ g_idl_node_free ((GIdlNode *)l->data);
+ g_list_free (iface->members);
+
+ }
+ break;
+
+ case G_IDL_NODE_VALUE:
+ {
+ GIdlNodeValue *value = (GIdlNodeValue *)node;
+
+ g_free (node->name);
+ g_free (value->c_name);
+ }
+ break;
+
+ case G_IDL_NODE_ENUM:
+ case G_IDL_NODE_FLAGS:
+ {
+ GIdlNodeEnum *enum_ = (GIdlNodeEnum *)node;
+
+ g_free (node->name);
+ for (l = enum_->values; l; l = l->next)
+ g_idl_node_free ((GIdlNode *)l->data);
+ g_list_free (enum_->values);
+ }
+ break;
+
+ case G_IDL_NODE_BOXED:
+ {
+ GIdlNodeBoxed *boxed = (GIdlNodeBoxed *)node;
+
+ g_free (node->name);
+ g_free (boxed->c_name);
+ g_free (boxed->init_func);
+
+ for (l = boxed->members; l; l = l->next)
+ g_idl_node_free ((GIdlNode *)l->data);
+ g_list_free (boxed->members);
+ }
+ break;
+
+ case G_IDL_NODE_STRUCT:
+ {
+ GIdlNodeStruct *struct_ = (GIdlNodeStruct *)node;
+
+ g_free (node->name);
+ for (l = struct_->members; l; l = l->next)
+ g_idl_node_free ((GIdlNode *)l->data);
+ g_list_free (struct_->members);
+ }
+ break;
+
+ case G_IDL_NODE_CONSTANT:
+ {
+ GIdlNodeConstant *constant = (GIdlNodeConstant *)node;
+
+ g_free (node->name);
+ g_free (constant->value);
+ g_idl_node_free ((GIdlNode *)constant->type);
+ }
+ break;
+
+ case G_IDL_NODE_ERROR_DOMAIN:
+ {
+ GIdlNodeErrorDomain *domain = (GIdlNodeErrorDomain *)node;
+
+ g_free (node->name);
+ g_free (domain->getquark);
+ g_free (domain->codes);
+ }
+ break;
+
+ case G_IDL_NODE_XREF:
+ {
+ GIdlNodeXRef *xref = (GIdlNodeXRef *)node;
+
+ g_free (node->name);
+ g_free (xref->namespace);
+ }
+ break;
+
+ default:
+ g_error ("Unhandled node type %d\n", node->type);
+ break;
+ }
+
+ g_free (node);
+}
+
+/* returns the fixed size of the blob */
+guint32
+g_idl_node_get_size (GIdlNode *node)
+{
+ GList *l;
+ gint size, n;
+
+ switch (node->type)
+ {
+ case G_IDL_NODE_CALLBACK:
+ size = 12;
+ break;
+
+ case G_IDL_NODE_FUNCTION:
+ size = 16;
+ break;
+
+ case G_IDL_NODE_PARAM:
+ size = 12;
+ break;
+
+ case G_IDL_NODE_TYPE:
+ size = 4;
+ break;
+
+ case G_IDL_NODE_OBJECT:
+ {
+ GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
+
+ n = g_list_length (iface->interfaces);
+ size = 32 + 2 * (n + (n % 2));
+
+ for (l = iface->members; l; l = l->next)
+ size += g_idl_node_get_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_INTERFACE:
+ {
+ GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
+
+ n = g_list_length (iface->prerequisites);
+ size = 28 + 2 * (n + (n % 2));
+
+ for (l = iface->members; l; l = l->next)
+ size += g_idl_node_get_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_ENUM:
+ case G_IDL_NODE_FLAGS:
+ {
+ GIdlNodeEnum *enum_ = (GIdlNodeEnum *)node;
+
+ n = g_list_length (enum_->values);
+ size = 20 + n * 16;
+ }
+ break;
+
+ case G_IDL_NODE_VALUE:
+ size = 16;
+ break;
+
+ case G_IDL_NODE_STRUCT:
+ case G_IDL_NODE_BOXED:
+ {
+ GIdlNodeBoxed *boxed = (GIdlNodeBoxed *)node;
+
+ size = 20;
+ for (l = boxed->members; l; l = l->next)
+ size += g_idl_node_get_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_PROPERTY:
+ size = 12;
+ break;
+
+ case G_IDL_NODE_SIGNAL:
+ size = 12;
+ break;
+
+ case G_IDL_NODE_VFUNC:
+ size = 16;
+ break;
+
+ case G_IDL_NODE_FIELD:
+ size = 12;
+ break;
+
+ case G_IDL_NODE_CONSTANT:
+ size = 20;
+ break;
+
+ case G_IDL_NODE_ERROR_DOMAIN:
+ size = 16;
+ break;
+
+ case G_IDL_NODE_XREF:
+ size = 0;
+ break;
+
+ default:
+ g_error ("Unhandled node type %d\n", node->type);
+ size = 0;
+ }
+
+ return size;
+}
+
+/* returns the full size of the blob including variable-size parts */
+guint32
+g_idl_node_get_full_size (GIdlNode *node)
+{
+ GList *l;
+ gint size, n;
+
+ switch (node->type)
+ {
+ case G_IDL_NODE_CALLBACK:
+ {
+ GIdlNodeFunction *function = (GIdlNodeFunction *)node;
+ size = 12;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ for (l = function->parameters; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ size += g_idl_node_get_full_size ((GIdlNode *)function->result);
+ }
+ break;
+
+ case G_IDL_NODE_FUNCTION:
+ {
+ GIdlNodeFunction *function = (GIdlNodeFunction *)node;
+ size = 16;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ size += ALIGN_VALUE (strlen (function->c_name) + 1, 4);
+ for (l = function->parameters; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ size += g_idl_node_get_full_size ((GIdlNode *)function->result);
+ }
+ break;
+
+ case G_IDL_NODE_PARAM:
+ {
+ GIdlNodeParam *param = (GIdlNodeParam *)node;
+
+ size = 12;
+ if (node->name)
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ size += g_idl_node_get_full_size ((GIdlNode *)param->type);
+ }
+ break;
+
+ case G_IDL_NODE_TYPE:
+ {
+ GIdlNodeType *type = (GIdlNodeType *)node;
+ if (type->tag < 20)
+ size = 4;
+ else
+ {
+ switch (type->tag)
+ {
+ case 20:
+ size = 4 + 4 + g_idl_node_get_full_size ((GIdlNode *)type->parameter_type1);
+ break;
+ case 21:
+ size = 4 + 4;
+ break;
+ case 22:
+ case 23:
+ size = 4 + 4 + g_idl_node_get_full_size ((GIdlNode *)type->parameter_type1);
+ break;
+ case 24:
+ size = 4 + 4
+ + g_idl_node_get_full_size ((GIdlNode *)type->parameter_type1)
+ + g_idl_node_get_full_size ((GIdlNode *)type->parameter_type2);
+ break;
+ case 25:
+ {
+ gint n = g_strv_length (type->errors);
+ size = 4 + 4 + 2 * (n + n % 2);
+ }
+ break;
+ default:
+ g_error ("Unknown type tag %d\n", type->tag);
+ break;
+ }
+ }
+ }
+ break;
+
+ case G_IDL_NODE_OBJECT:
+ {
+ GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
+
+ n = g_list_length (iface->interfaces);
+ size = 32;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ size += ALIGN_VALUE (strlen (iface->c_name) + 1, 4);
+ size += ALIGN_VALUE (strlen (iface->init_func) + 1, 4);
+ size += 2 * (n + (n % 2));
+
+ for (l = iface->members; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_INTERFACE:
+ {
+ GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
+
+ n = g_list_length (iface->prerequisites);
+ size = 28;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ size += ALIGN_VALUE (strlen (iface->c_name) + 1, 4);
+ size += ALIGN_VALUE (strlen (iface->init_func) + 1, 4);
+ size += 2 * (n + (n % 2));
+
+ for (l = iface->members; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_ENUM:
+ case G_IDL_NODE_FLAGS:
+ {
+ GIdlNodeEnum *enum_ = (GIdlNodeEnum *)node;
+
+ size = 20;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ size += ALIGN_VALUE (strlen (enum_->c_name) + 1, 4);
+ if (enum_->init_func)
+ size += ALIGN_VALUE (strlen (enum_->init_func) + 1, 4);
+
+ for (l = enum_->values; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_VALUE:
+ {
+ GIdlNodeValue *value = (GIdlNodeValue *)node;
+
+ size = 16;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ size += ALIGN_VALUE (strlen (value->c_name) + 1, 4);
+ }
+ break;
+
+ case G_IDL_NODE_STRUCT:
+ {
+ GIdlNodeStruct *struct_ = (GIdlNodeStruct *)node;
+
+ size = 20;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ for (l = struct_->members; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_BOXED:
+ {
+ GIdlNodeBoxed *boxed = (GIdlNodeBoxed *)node;
+
+ size = 20;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ if (boxed->c_name)
+ size += ALIGN_VALUE (strlen (boxed->c_name) + 1, 4);
+ if (boxed->init_func)
+ size += ALIGN_VALUE (strlen (boxed->init_func) + 1, 4);
+ for (l = boxed->members; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ }
+ break;
+
+ case G_IDL_NODE_PROPERTY:
+ {
+ GIdlNodeProperty *prop = (GIdlNodeProperty *)node;
+
+ size = 12;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ size += g_idl_node_get_full_size ((GIdlNode *)prop->type);
+ }
+ break;
+
+ case G_IDL_NODE_SIGNAL:
+ {
+ GIdlNodeSignal *signal = (GIdlNodeSignal *)node;
+
+ size = 12;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ for (l = signal->parameters; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ size += g_idl_node_get_full_size ((GIdlNode *)signal->result);
+ }
+ break;
+
+ case G_IDL_NODE_VFUNC:
+ {
+ GIdlNodeVFunc *vfunc = (GIdlNodeVFunc *)node;
+
+ size = 16;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ for (l = vfunc->parameters; l; l = l->next)
+ size += g_idl_node_get_full_size ((GIdlNode *)l->data);
+ size += g_idl_node_get_full_size ((GIdlNode *)vfunc->result);
+ }
+ break;
+
+ case G_IDL_NODE_FIELD:
+ {
+ GIdlNodeField *field = (GIdlNodeField *)node;
+
+ size = 12;
+ size += ALIGN_VALUE (strlen (field->c_name) + 1, 4);
+ size += g_idl_node_get_full_size ((GIdlNode *)field->type);
+ }
+ break;
+
+ case G_IDL_NODE_CONSTANT:
+ {
+ GIdlNodeConstant *constant = (GIdlNodeConstant *)node;
+
+ size = 20;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ /* FIXME non-string values */
+ size += ALIGN_VALUE (strlen (constant->value) + 1, 4);
+ size += g_idl_node_get_full_size ((GIdlNode *)constant->type);
+ }
+ break;
+
+ case G_IDL_NODE_ERROR_DOMAIN:
+ {
+ GIdlNodeErrorDomain *domain = (GIdlNodeErrorDomain *)node;
+
+ size = 16;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ size += ALIGN_VALUE (strlen (domain->getquark) + 1, 4);
+ }
+ break;
+
+ case G_IDL_NODE_XREF:
+ {
+ GIdlNodeXRef *xref = (GIdlNodeXRef *)node;
+
+ size = 0;
+ size += ALIGN_VALUE (strlen (node->name) + 1, 4);
+ size += ALIGN_VALUE (strlen (xref->namespace) + 1, 4);
+ }
+ break;
+
+ default:
+ g_error ("Unknown type tag %d\n", node->type);
+ size = 0;
+ }
+
+ return size;
+}
+
+static gint64
+parse_int_value (const gchar *str)
+{
+ return strtoll (str, NULL, 0);
+}
+
+static guint64
+parse_uint_value (const gchar *str)
+{
+ return strtoull (str, NULL, 0);
+}
+
+static gdouble
+parse_float_value (const gchar *str)
+{
+ return strtod (str, NULL);
+}
+
+static gboolean
+parse_boolean_value (const gchar *str)
+{
+ if (strcmp (str, "TRUE") == 0)
+ return TRUE;
+
+ if (strcmp (str, "FALSE") == 0)
+ return FALSE;
+
+ return parse_int_value (str) ? TRUE : FALSE;
+}
+
+static GIdlNode *
+find_entry_node (GIdlModule *module,
+ GList *modules,
+ const gchar *name,
+ guint16 *idx)
+{
+ GList *l, *m;
+ gint i;
+
+ for (l = module->entries, i = 0; l; l = l->next, i++)
+ {
+ GIdlNode *node = (GIdlNode *)l->data;
+
+ if (strcmp (node->name, name) == 0)
+ {
+ if (idx)
+ *idx = i;
+ return node;
+ }
+ }
+
+ for (m = modules; m; m = m->next)
+ {
+ GIdlModule *foreign = (GIdlModule *)m->data;
+
+ if (foreign == module)
+ continue;
+
+ for (l = foreign->entries; l; l = l->next)
+ {
+ GIdlNode *node = (GIdlNode *)l->data;
+
+ if (node->type == G_IDL_NODE_XREF)
+ continue;
+
+ if (strcmp (node->name, name) == 0)
+ {
+ GIdlNode *xref = g_idl_node_new (G_IDL_NODE_XREF);
+ xref->name = g_strdup (name);
+ ((GIdlNodeXRef *)xref)->namespace = g_strdup (foreign->name);
+
+ module->entries = g_list_append (module->entries, xref);
+
+ if (idx)
+ *idx = g_list_length (module->entries) - 1;
+
+ return xref;
+ }
+ }
+ }
+
+ g_warning ("No such entry: '%s'\n", name);
+
+ return NULL;
+}
+
+static guint16
+find_entry (GIdlModule *module,
+ GList *modules,
+ const gchar *name)
+{
+ guint16 idx;
+
+ find_entry_node (module, modules, name, &idx);
+
+ return idx;
+}
+
+static void
+serialize_type (GIdlModule *module,
+ GList *modules,
+ GIdlNodeType *node,
+ GString *str)
+{
+ gint i;
+
+ const gchar* basic[] = {
+ "void",
+ "gboolean",
+ "gint8",
+ "guint8",
+ "gint16",
+ "guint16",
+ "gint32",
+ "guint32",
+ "gint64",
+ "guint64",
+ "gfloat",
+ "gdouble",
+ "gchar",
+ "GString",
+ "gint",
+ "guint",
+ "glong",
+ "gulong"
+ };
+
+ if (node->tag < 20)
+ {
+ g_string_append_printf (str, "%s%s",
+ basic[node->tag], node->is_pointer ? "*" : "");
+ }
+ else if (node->tag == 20)
+ {
+ serialize_type (module, modules, node->parameter_type1, str);
+ g_string_append (str, "[");
+
+ if (node->has_length)
+ g_string_append_printf (str, "length=%d", node->length);
+
+ if (node->zero_terminated)
+ g_string_append_printf (str, "%szero-terminated=1",
+ node->has_length ? "," : "");
+
+ g_string_append (str, "]");
+ }
+ else if (node->tag == 21)
+ {
+ GIdlNode *iface;
+
+ iface = find_entry_node (module, modules, node->interface, NULL);
+ g_string_append_printf (str, "%s%s",
+ iface->name, node->is_pointer ? "*" : "");
+ }
+ else if (node->tag == 22)
+ {
+ g_string_append (str, "GList<");
+ serialize_type (module, modules, node->parameter_type1, str);
+ g_string_append (str, ">");
+ }
+ else if (node->tag == 23)
+ {
+ g_string_append (str, "GSList<");
+ serialize_type (module, modules, node->parameter_type1, str);
+ g_string_append (str, ">");
+ }
+ else if (node->tag == 24)
+ {
+ g_string_append (str, "GHashTable<");
+ serialize_type (module, modules, node->parameter_type1, str);
+ g_string_append (str, ",");
+ serialize_type (module, modules, node->parameter_type2, str);
+ g_string_append (str, ">");
+ }
+ else if (node->tag == 25)
+ {
+ g_string_append (str, "GError<");
+ for (i = 0; node->errors[i]; i++)
+ {
+ if (i > 0)
+ g_string_append (str, ",");
+ g_string_append (str, node->errors[i]);
+ }
+ g_string_append (str, ">");
+ }
+}
+
+void
+g_idl_node_build_metadata (GIdlNode *node,
+ GIdlModule *module,
+ GList *modules,
+ GHashTable *strings,
+ GHashTable *types,
+ guchar *data,
+ guint32 *offset,
+ guint32 *offset2)
+{
+ GList *l;
+
+ switch (node->type)
+ {
+ case G_IDL_NODE_TYPE:
+ {
+ GIdlNodeType *type = (GIdlNodeType *)node;
+ SimpleTypeBlob *blob = (SimpleTypeBlob *)&data[*offset];
+
+ *offset += 4;
+
+ if (type->tag < 20)
+ {
+ blob->reserved = 0;
+ blob->reserved2 = 0;
+ blob->pointer = type->is_pointer;
+ blob->reserved3 = 0;
+ blob->tag = type->tag;
+ }
+ else
+ {
+ GString *str;
+ gchar *s;
+ gpointer value;
+
+ str = g_string_new (0);
+ serialize_type (module, modules, type, str);
+ s = g_string_free (str, FALSE);
+
+ value = g_hash_table_lookup (types, s);
+ if (value)
+ {
+ blob->offset = GPOINTER_TO_INT (value);
+ g_free (s);
+ }
+ else
+ {
+ g_hash_table_insert (types, s, GINT_TO_POINTER(*offset2));
+
+ blob->offset = *offset2;
+ switch (type->tag)
+ {
+ case 20:
+ {
+ ArrayTypeBlob *array = (ArrayTypeBlob *)&data[*offset2];
+ guint32 pos;
+
+ array->pointer = 1;
+ array->reserved = 0;
+ array->tag = type->tag;
+ array->zero_terminated = type->zero_terminated;
+ array->has_length = type->has_length;
+ array->reserved2 = 0;
+ array->length = type->length;
+
+ pos = *offset2 + 4;
+ *offset2 += 8;
+
+ g_idl_node_build_metadata ((GIdlNode *)type->parameter_type1,
+ module, modules, strings, types,
+ data, &pos, offset2);
+ }
+ break;
+
+ case 21:
+ {
+ InterfaceTypeBlob *iface = (InterfaceTypeBlob *)&data[*offset2];
+ gint i, interface;
+
+ *offset2 += 4;
+
+ iface->pointer = 1;
+ iface->reserved = 0;
+ iface->tag = type->tag;
+ iface->reserved2 = 0;
+ iface->interface = 0;
+ iface->interface = find_entry (module, modules, type->interface);
+ }
+ break;
+
+ case 22:
+ case 23:
+ {
+ ParamTypeBlob *param = (ParamTypeBlob *)&data[*offset2];
+ guint32 pos;
+
+ param->pointer = 1;
+ param->reserved = 0;
+ param->tag = type->tag;
+ param->reserved2 = 0;
+ param->n_types = 1;
+
+ pos = *offset2 + 4;
+ *offset2 += 8;
+
+ g_idl_node_build_metadata ((GIdlNode *)type->parameter_type1,
+ module, modules, strings, types,
+ data, &pos, offset2);
+ }
+ break;
+
+ case 24:
+ {
+ ParamTypeBlob *param = (ParamTypeBlob *)&data[*offset2];
+ guint32 pos;
+
+ param->pointer = 1;
+ param->reserved = 0;
+ param->tag = type->tag;
+ param->reserved2 = 0;
+ param->n_types = 2;
+
+ pos = *offset2 + 4;
+ *offset2 += 12;
+
+ g_idl_node_build_metadata ((GIdlNode *)type->parameter_type1,
+ module, modules, strings, types,
+ data, &pos, offset2);
+ g_idl_node_build_metadata ((GIdlNode *)type->parameter_type2,
+ module, modules, strings, types,
+ data, &pos, offset2);
+ }
+ break;
+
+ case 25:
+ {
+ ErrorTypeBlob *blob = (ErrorTypeBlob *)&data[*offset2];
+ gint i, domain;
+
+ blob->pointer = 1;
+ blob->reserved = 0;
+ blob->tag = type->tag;
+ blob->reserved2 = 0;
+ blob->n_domains = g_strv_length (type->errors);
+
+ *offset2 = ALIGN_VALUE (*offset2 + 4 + 2 * blob->n_domains, 4);
+ for (i = 0; type->errors[i]; i++)
+ blob->domains[i] = find_entry (module, modules, type->errors[i]);
+ }
+ break;
+
+ default:
+ g_error ("Unknown type tag %d\n", type->tag);
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case G_IDL_NODE_FIELD:
+ {
+ GIdlNodeField *field = (GIdlNodeField *)node;
+ FieldBlob *blob;
+
+ blob = (FieldBlob *)&data[*offset];
+ *offset += 8;
+
+ blob->name = write_string (field->c_name, strings, data, offset2);
+ blob->readable = field->readable;
+ blob->writable = field->writable;
+ blob->reserved = 0;
+ blob->bits = 0;
+ blob->struct_offset = 0;
+
+ g_idl_node_build_metadata ((GIdlNode *)field->type,
+ module, modules, strings, types,
+ data, offset, offset2);
+ }
+ break;
+
+ case G_IDL_NODE_PROPERTY:
+ {
+ GIdlNodeProperty *prop = (GIdlNodeProperty *)node;
+ PropertyBlob *blob = (PropertyBlob *)&data[*offset];
+ *offset += 8;
+
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->deprecated = prop->deprecated;
+ blob->readable = prop->readable;
+ blob->writable = prop->writable;
+ blob->construct = prop->construct;
+ blob->construct_only = prop->construct_only;
+ blob->reserved = 0;
+
+ g_idl_node_build_metadata ((GIdlNode *)prop->type,
+ module, modules, strings, types,
+ data, offset, offset2);
+ }
+ break;
+
+ case G_IDL_NODE_FUNCTION:
+ {
+ FunctionBlob *blob = (FunctionBlob *)&data[*offset];
+ SignatureBlob *blob2 = (SignatureBlob *)&data[*offset2];
+ GIdlNodeFunction *function = (GIdlNodeFunction *)node;
+ guint32 signature, res;
+ gint n;
+
+ signature = *offset2;
+ n = g_list_length (function->parameters);
+
+ *offset += 16;
+ *offset2 += 8 + n * 12;
+
+ blob->blob_type = BLOB_TYPE_FUNCTION;
+ blob->deprecated = function->deprecated;
+ blob->setter = function->is_setter;
+ blob->getter = function->is_getter;
+ blob->constructor = function->is_constructor;
+ blob->wraps_vfunc = function->wraps_vfunc;
+ blob->reserved = 0;
+ blob->index = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->c_name = write_string (function->c_name, strings, data, offset2);
+ blob->signature = signature;
+
+ g_idl_node_build_metadata ((GIdlNode *)function->result->type,
+ module, modules, strings, types,
+ data, &signature, offset2);
+
+ blob2->may_return_null = function->result->null_ok;
+ blob2->caller_owns_return_value = function->result->transfer;
+ blob2->caller_owns_return_container = function->result->shallow_transfer;
+ blob2->reserved = 0;
+ blob2->n_arguments = n;
+
+ signature += 4;
+
+ for (l = function->parameters; l; l = l->next)
+ {
+ GIdlNode *param = (GIdlNode *)l->data;
+
+ g_idl_node_build_metadata (param,
+ module, modules, strings, types,
+ data, &signature, offset2);
+ }
+ }
+ break;
+
+ case G_IDL_NODE_CALLBACK:
+ {
+ CallbackBlob *blob = (CallbackBlob *)&data[*offset];
+ SignatureBlob *blob2 = (SignatureBlob *)&data[*offset2];
+ GIdlNodeFunction *function = (GIdlNodeFunction *)node;
+ guint32 signature, res;
+ gint n;
+
+ signature = *offset2;
+ n = g_list_length (function->parameters);
+
+ *offset += 12;
+ *offset2 += 8 + n * 12;
+
+ blob->blob_type = BLOB_TYPE_CALLBACK;
+ blob->deprecated = function->deprecated;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->signature = signature;
+
+ g_idl_node_build_metadata ((GIdlNode *)function->result->type,
+ module, modules, strings, types,
+ data, &signature, offset2);
+
+ blob2->may_return_null = function->result->null_ok;
+ blob2->caller_owns_return_value = function->result->transfer;
+ blob2->caller_owns_return_container = function->result->shallow_transfer;
+ blob2->reserved = 0;
+ blob2->n_arguments = n;
+
+ signature += 4;
+
+ for (l = function->parameters; l; l = l->next)
+ {
+ GIdlNode *param = (GIdlNode *)l->data;
+
+ g_idl_node_build_metadata (param,
+ module, modules, strings, types,
+ data, &signature, offset2);
+ }
+ }
+ break;
+
+ case G_IDL_NODE_SIGNAL:
+ {
+ SignalBlob *blob = (SignalBlob *)&data[*offset];
+ SignatureBlob *blob2 = (SignatureBlob *)&data[*offset2];
+ GIdlNodeSignal *signal = (GIdlNodeSignal *)node;
+ guint32 signature, res;
+ gint n;
+
+ signature = *offset2;
+ n = g_list_length (signal->parameters);
+
+ *offset += 12;
+ *offset2 += 8 + n * 12;
+
+ blob->deprecated = signal->deprecated;
+ blob->run_first = signal->run_first;
+ blob->run_last = signal->run_last;
+ blob->run_cleanup = signal->run_cleanup;
+ blob->no_recurse = signal->no_recurse;
+ blob->detailed = signal->detailed;
+ blob->action = signal->action;
+ blob->no_hooks = signal->no_hooks;
+ blob->has_class_closure = 0; /* FIXME */
+ blob->true_stops_emit = 0; /* FIXME */
+ blob->reserved = 0;
+ blob->class_closure = 0; /* FIXME */
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->signature = signature;
+
+ g_idl_node_build_metadata ((GIdlNode *)signal->result->type,
+ module, modules, strings, types,
+ data, &signature, offset2);
+
+ blob2->may_return_null = signal->result->null_ok;
+ blob2->caller_owns_return_value = signal->result->transfer;
+ blob2->caller_owns_return_container = signal->result->shallow_transfer;
+ blob2->reserved = 0;
+ blob2->n_arguments = n;
+
+ signature += 4;
+
+ for (l = signal->parameters; l; l = l->next)
+ {
+ GIdlNode *param = (GIdlNode *)l->data;
+
+ g_idl_node_build_metadata (param, module, modules, strings, types,
+ data, &signature, offset2);
+ }
+ }
+ break;
+
+ case G_IDL_NODE_VFUNC:
+ {
+ VFuncBlob *blob = (VFuncBlob *)&data[*offset];
+ SignatureBlob *blob2 = (SignatureBlob *)&data[*offset2];
+ GIdlNodeVFunc *vfunc = (GIdlNodeVFunc *)node;
+ guint32 signature, res;
+ gint n;
+
+ signature = *offset2;
+ n = g_list_length (vfunc->parameters);
+
+ *offset += 16;
+ *offset2 += 8 + n * 12;
+
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->must_chain_up = 0; /* FIXME */
+ blob->must_be_implemented = 0; /* FIXME */
+ blob->must_not_be_implemented = 0; /* FIXME */
+ blob->class_closure = 0; /* FIXME */
+ blob->reserved = 0;
+
+ blob->struct_offset = 0; /* FIXME */
+ blob->reserved2 = 0;
+ blob->signature = signature;
+
+ g_idl_node_build_metadata ((GIdlNode *)vfunc->result->type,
+ module, modules, strings, types,
+ data, &signature, offset2);
+
+ blob2->may_return_null = vfunc->result->null_ok;
+ blob2->caller_owns_return_value = vfunc->result->transfer;
+ blob2->caller_owns_return_container = vfunc->result->shallow_transfer;
+ blob2->reserved = 0;
+ blob2->n_arguments = n;
+
+ signature += 4;
+
+ for (l = vfunc->parameters; l; l = l->next)
+ {
+ GIdlNode *param = (GIdlNode *)l->data;
+
+ g_idl_node_build_metadata (param, module, modules, strings,
+ types, data, &signature, offset2);
+ }
+ }
+ break;
+
+ case G_IDL_NODE_PARAM:
+ {
+ ArgBlob *blob = (ArgBlob *)&data[*offset];
+ GIdlNodeParam *param = (GIdlNodeParam *)node;
+ guint32 res;
+
+ *offset += 8;
+
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->in = param->in;
+ blob->out = param->out;
+ blob->dipper = param->dipper;
+ blob->null_ok = param->null_ok;
+ blob->optional = param->optional;
+ blob->transfer_ownership = param->transfer;
+ blob->transfer_container_ownership = param->shallow_transfer;
+ blob->return_value = param->retval;
+ blob->reserved = 0;
+
+ g_idl_node_build_metadata ((GIdlNode *)param->type, module, modules,
+ types, strings, data, offset, offset2);
+ }
+ break;
+
+ case G_IDL_NODE_STRUCT:
+ {
+ StructBlob *blob = (StructBlob *)&data[*offset];
+ GIdlNodeStruct *struct_ = (GIdlNodeStruct *)node;
+ guint32 pos;
+
+ blob->blob_type = BLOB_TYPE_STRUCT;
+ blob->deprecated = struct_->deprecated;
+ blob->unregistered = TRUE;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->gtype_name = 0;
+ blob->gtype_init = 0;
+
+ blob->n_fields = 0;
+ blob->n_methods = 0;
+
+ *offset += 20;
+ for (l = struct_->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_FIELD)
+ {
+ blob->n_fields++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ for (l = struct_->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_FUNCTION)
+ {
+ blob->n_methods++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+ }
+ break;
+
+ case G_IDL_NODE_BOXED:
+ {
+ StructBlob *blob = (StructBlob *)&data[*offset];
+ GIdlNodeBoxed *boxed = (GIdlNodeBoxed *)node;
+
+ blob->blob_type = BLOB_TYPE_BOXED;
+ blob->deprecated = boxed->deprecated;
+ blob->unregistered = FALSE;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->gtype_name = write_string (boxed->c_name, strings, data, offset2);
+ blob->gtype_init = write_string (boxed->init_func, strings, data, offset2);
+
+ blob->n_fields = 0;
+ blob->n_methods = 0;
+
+ *offset += 20;
+ for (l = boxed->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_FIELD)
+ {
+ blob->n_fields++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ for (l = boxed->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_FUNCTION)
+ {
+ blob->n_methods++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+ }
+ break;
+
+ case G_IDL_NODE_ENUM:
+ case G_IDL_NODE_FLAGS:
+ {
+ EnumBlob *blob = (EnumBlob *)&data[*offset];
+ GIdlNodeEnum *enum_ = (GIdlNodeEnum *)node;
+
+ *offset += 20;
+
+ if (node->type == G_IDL_NODE_ENUM)
+ blob->blob_type = BLOB_TYPE_ENUM;
+ else
+ blob->blob_type = BLOB_TYPE_FLAGS;
+
+ blob->deprecated = enum_->deprecated;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->gtype_name = write_string (enum_->c_name, strings, data, offset2);
+ if (enum_->init_func)
+ {
+ blob->unregistered = FALSE;
+ blob->gtype_init = write_string (enum_->init_func, strings, data, offset2);
+ }
+ else
+ {
+ blob->unregistered = TRUE;
+ blob->gtype_init = 0;
+ }
+
+ blob->n_values = 0;
+ blob->reserved2 = 0;
+
+ for (l = enum_->values; l; l = l->next)
+ {
+ GIdlNode *value = (GIdlNode *)l->data;
+
+ blob->n_values++;
+ g_idl_node_build_metadata (value, module, modules, strings, types,
+ data, offset, offset2);
+ }
+ }
+ break;
+
+ case G_IDL_NODE_OBJECT:
+ {
+ ObjectBlob *blob = (ObjectBlob *)&data[*offset];
+ GIdlNodeInterface *object = (GIdlNodeInterface *)node;
+ gint parent;
+
+ blob->blob_type = BLOB_TYPE_OBJECT;
+ blob->deprecated = object->deprecated;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->gtype_name = write_string (object->c_name, strings, data, offset2);
+ blob->gtype_init = write_string (object->init_func, strings, data, offset2);
+ if (object->parent)
+ blob->parent = find_entry (module, modules, object->parent);
+ else
+ blob->parent = 0;
+
+ blob->n_interfaces = 0;
+ blob->n_fields = 0;
+ blob->n_properties = 0;
+ blob->n_methods = 0;
+ blob->n_signals = 0;
+ blob->n_vfuncs = 0;
+ blob->n_constants = 0;
+
+ *offset += 32;
+ for (l = object->interfaces; l; l = l->next)
+ {
+ blob->n_interfaces++;
+ *(guint16*)&data[*offset] = find_entry (module, modules, (gchar *)l->data);
+ *offset += 2;
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_FIELD)
+ {
+ blob->n_fields++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_PROPERTY)
+ {
+ blob->n_properties++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_FUNCTION)
+ {
+ blob->n_methods++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_SIGNAL)
+ {
+ blob->n_signals++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_VFUNC)
+ {
+ blob->n_vfuncs++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = object->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_CONSTANT)
+ {
+ blob->n_constants++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+ }
+ break;
+
+ case G_IDL_NODE_INTERFACE:
+ {
+ InterfaceBlob *blob = (InterfaceBlob *)&data[*offset];
+ GIdlNodeInterface *iface = (GIdlNodeInterface *)node;
+ gint parent;
+
+ blob->blob_type = BLOB_TYPE_INTERFACE;
+ blob->deprecated = iface->deprecated;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->gtype_name = write_string (iface->c_name, strings, data, offset2);
+ blob->gtype_init = write_string (iface->init_func, strings, data, offset2);
+ blob->n_prerequisites = 0;
+ blob->n_properties = 0;
+ blob->n_methods = 0;
+ blob->n_signals = 0;
+ blob->n_vfuncs = 0;
+ blob->n_constants = 0;
+
+ *offset += 28;
+ for (l = iface->prerequisites; l; l = l->next)
+ {
+ blob->n_prerequisites++;
+ *(guint16*)&data[*offset] = find_entry (module, modules, (gchar *)l->data);
+ *offset += 2;
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = iface->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_PROPERTY)
+ {
+ blob->n_properties++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = iface->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_FUNCTION)
+ {
+ blob->n_methods++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = iface->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_SIGNAL)
+ {
+ blob->n_signals++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = iface->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_VFUNC)
+ {
+ blob->n_vfuncs++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+
+ *offset = ALIGN_VALUE (*offset, 4);
+ for (l = iface->members; l; l = l->next)
+ {
+ GIdlNode *member = (GIdlNode *)l->data;
+
+ if (member->type == G_IDL_NODE_CONSTANT)
+ {
+ blob->n_constants++;
+ g_idl_node_build_metadata (member, module, modules, strings,
+ types, data, offset, offset2);
+ }
+ }
+ }
+ break;
+
+
+ case G_IDL_NODE_VALUE:
+ {
+ GIdlNodeValue *value = (GIdlNodeValue *)node;
+ ValueBlob *blob = (ValueBlob *)&data[*offset];
+ *offset += 16;
+
+ blob->deprecated = value->deprecated;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->short_name = write_string (value->c_name, strings, data, offset2);
+ blob->value = value->value;
+ }
+ break;
+
+ case G_IDL_NODE_ERROR_DOMAIN:
+ {
+ GIdlNodeErrorDomain *domain = (GIdlNodeErrorDomain *)node;
+ ErrorDomainBlob *blob = (ErrorDomainBlob *)&data[*offset];
+ *offset += 16;
+
+ blob->blob_type = BLOB_TYPE_ERROR_DOMAIN;
+ blob->deprecated = domain->deprecated;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+ blob->get_quark = write_string (domain->getquark, strings, data, offset2);
+ blob->error_codes = find_entry (module, modules, domain->codes);
+ blob->reserved2 = 0;
+ }
+ break;
+
+ case G_IDL_NODE_CONSTANT:
+ {
+ GIdlNodeConstant *constant = (GIdlNodeConstant *)node;
+ ConstantBlob *blob = (ConstantBlob *)&data[*offset];
+ gint pos;
+
+ pos = *offset + 8;
+ *offset += 20;
+
+ blob->blob_type = BLOB_TYPE_CONSTANT;
+ blob->deprecated = constant->deprecated;
+ blob->reserved = 0;
+ blob->name = write_string (node->name, strings, data, offset2);
+
+ blob->offset = *offset2;
+ switch (constant->type->tag)
+ {
+ case 1:
+ blob->size = 4;
+ *(gboolean*)&data[blob->offset] = parse_boolean_value (constant->value);
+ break;
+ case 2:
+ blob->size = 1;
+ *(gint8*)&data[blob->offset] = (gint8) parse_int_value (constant->value);
+ break;
+ case 3:
+ blob->size = 1;
+ *(guint8*)&data[blob->offset] = (guint8) parse_uint_value (constant->value);
+ break;
+ case 4:
+ blob->size = 2;
+ *(gint16*)&data[blob->offset] = (gint16) parse_int_value (constant->value);
+ break;
+ case 5:
+ blob->size = 2;
+ *(guint16*)&data[blob->offset] = (guint16) parse_uint_value (constant->value);
+ break;
+ case 6:
+ blob->size = 4;
+ *(gint32*)&data[blob->offset] = (gint32) parse_int_value (constant->value);
+ break;
+ case 7:
+ blob->size = 4;
+ *(guint32*)&data[blob->offset] = (guint32) parse_uint_value (constant->value);
+ break;
+ case 8:
+ blob->size = 8;
+ *(gint32*)&data[blob->offset] = (gint64) parse_int_value (constant->value);
+ break;
+ case 9:
+ blob->size = 8;
+ *(guint32*)&data[blob->offset] = (guint64) parse_uint_value (constant->value);
+ break;
+ case 10:
+ blob->size = sizeof (gfloat);
+ *(gfloat*)&data[blob->offset] = (gfloat) parse_float_value (constant->value);
+ break;
+ case 11:
+ blob->size = sizeof (gdouble);
+ *(gdouble*)&data[blob->offset] = (gdouble) parse_float_value (constant->value);
+ break;
+ case 12:
+ blob->size = strlen (constant->value) + 1;
+ memcpy (&data[blob->offset], constant->value, blob->size);
+ break;
+ case 14:
+ blob->size = sizeof (gint);
+ *(gint*)&data[blob->offset] = (gint) parse_int_value (constant->value);
+ break;
+ case 15:
+ blob->size = sizeof (guint);
+ *(gint*)&data[blob->offset] = (guint) parse_uint_value (constant->value);
+ break;
+ case 16:
+ blob->size = sizeof (glong);
+ *(glong*)&data[blob->offset] = (glong) parse_int_value (constant->value);
+ break;
+ case 17:
+ blob->size = sizeof (gulong);
+ *(gulong*)&data[blob->offset] = (gulong) parse_uint_value (constant->value);
+ break;
+ }
+ *offset2 += ALIGN_VALUE (blob->size, 4);
+
+ g_idl_node_build_metadata ((GIdlNode *)constant->type, module, modules,
+ strings, types, data, &pos, offset2);
+ }
+ break;
+ }
+}
+
+
+/* if str is already in the pool, return previous location, otherwise write str
+ * to the metadata at offset, put it in the pool and update offset. If the
+ * metadata is not large enough to hold the string, reallocate it.
+ */
+guint32
+write_string (const gchar *str,
+ GHashTable *strings,
+ guchar *data,
+ guint32 *offset)
+{
+ gpointer value;
+ guint32 start;
+
+ value = g_hash_table_lookup (strings, str);
+
+ if (value)
+ return GPOINTER_TO_INT (value);
+
+ g_hash_table_insert (strings, (gpointer)str, GINT_TO_POINTER (*offset));
+
+ start = *offset;
+ *offset = ALIGN_VALUE (start + strlen (str) + 1, 4);
+
+ strcpy (&data[start], str);
+
+ return start;
+}
diff --git a/src/gidlnode.h b/src/gidlnode.h
new file mode 100644
index 00000000..08683d31
--- /dev/null
+++ b/src/gidlnode.h
@@ -0,0 +1,313 @@
+/* GObject introspection: Parsed IDL
+ *
+ * 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_IDL_NODE_H__
+#define __G_IDL_NODE_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GIdlNode GIdlNode;
+typedef struct _GIdlNodeFunction GIdlNodeFunction;
+typedef struct _GIdlNodeParam GIdlNodeParam;
+typedef struct _GIdlNodeType GIdlNodeType;
+typedef struct _GIdlNodeInterface GIdlNodeInterface;
+typedef struct _GIdlNodeSignal GIdlNodeSignal;
+typedef struct _GIdlNodeProperty GIdlNodeProperty;
+typedef struct _GIdlNodeVFunc GIdlNodeVFunc;
+typedef struct _GIdlNodeField GIdlNodeField;
+typedef struct _GIdlNodeValue GIdlNodeValue;
+typedef struct _GIdlNodeEnum GIdlNodeEnum;
+typedef struct _GIdlNodeBoxed GIdlNodeBoxed;
+typedef struct _GIdlNodeStruct GIdlNodeStruct;
+typedef struct _GIdlNodeConstant GIdlNodeConstant;
+typedef struct _GIdlNodeErrorDomain GIdlNodeErrorDomain;
+typedef struct _GIdlNodeXRef GIdlNodeXRef;
+
+typedef enum
+{
+ G_IDL_NODE_INVALID,
+ G_IDL_NODE_FUNCTION,
+ G_IDL_NODE_CALLBACK,
+ G_IDL_NODE_STRUCT,
+ G_IDL_NODE_BOXED,
+ G_IDL_NODE_ENUM,
+ G_IDL_NODE_FLAGS,
+ G_IDL_NODE_OBJECT,
+ G_IDL_NODE_INTERFACE,
+ G_IDL_NODE_CONSTANT,
+ G_IDL_NODE_ERROR_DOMAIN,
+ G_IDL_NODE_PARAM,
+ G_IDL_NODE_TYPE,
+ G_IDL_NODE_PROPERTY,
+ G_IDL_NODE_SIGNAL,
+ G_IDL_NODE_VALUE,
+ G_IDL_NODE_VFUNC,
+ G_IDL_NODE_FIELD,
+ G_IDL_NODE_XREF
+} GIdlNodeTypeId;
+
+struct _GIdlNode
+{
+ GIdlNodeTypeId type;
+ gchar *name;
+};
+
+struct _GIdlNodeXRef
+{
+ GIdlNode node;
+
+ gchar *namespace;
+};
+
+struct _GIdlNodeFunction
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ gboolean is_method;
+ gboolean is_setter;
+ gboolean is_getter;
+ gboolean is_constructor;
+ gboolean wraps_vfunc;
+
+ gchar *c_name;
+
+ GIdlNodeParam *result;
+ GList *parameters;
+};
+
+struct _GIdlNodeType
+{
+ GIdlNode node;
+
+ gboolean is_pointer;
+ gboolean is_basic;
+ gboolean is_array;
+ gboolean is_glist;
+ gboolean is_gslist;
+ gboolean is_ghashtable;
+ gboolean is_interface;
+ gboolean is_error;
+ gint tag;
+
+ gchar *unparsed;
+
+ gboolean zero_terminated;
+ gboolean has_length;
+ gint length;
+
+ GIdlNodeType *parameter_type1;
+ GIdlNodeType *parameter_type2;
+
+ gchar *interface;
+ gchar **errors;
+};
+
+struct _GIdlNodeParam
+{
+ GIdlNode node;
+
+ gboolean in;
+ gboolean out;
+ gboolean dipper;
+ gboolean optional;
+ gboolean retval;
+ gboolean null_ok;
+ gboolean transfer;
+ gboolean shallow_transfer;
+
+ GIdlNodeType *type;
+};
+
+struct _GIdlNodeProperty
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ gchar *c_name;
+ gboolean readable;
+ gboolean writable;
+ gboolean construct;
+ gboolean construct_only;
+
+ GIdlNodeType *type;
+};
+
+struct _GIdlNodeSignal
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ gchar *c_name;
+ gboolean run_first;
+ gboolean run_last;
+ gboolean run_cleanup;
+ gboolean no_recurse;
+ gboolean detailed;
+ gboolean action;
+ gboolean no_hooks;
+
+ gboolean has_class_closure;
+ gboolean true_stops_emit;
+
+ gint class_closure;
+
+ GList *parameters;
+ GIdlNodeParam *result;
+};
+
+struct _GIdlNodeVFunc
+{
+ GIdlNode node;
+
+ gchar *c_name;
+ gboolean must_chain_up;
+ gboolean must_be_implemented;
+ gboolean must_not_be_implemented;
+ gboolean is_class_closure;
+
+ GList *parameters;
+ GIdlNodeParam *result;
+};
+
+struct _GIdlNodeField
+{
+ GIdlNode node;
+
+ gchar *c_name;
+ gboolean readable;
+ gboolean writable;
+ gint bits;
+
+ GIdlNodeType *type;
+};
+
+struct _GIdlNodeInterface
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ gchar *c_name;
+ gchar *init_func;
+
+ gchar *parent;
+
+ GList *interfaces;
+ GList *prerequisites;
+
+ GList *members;
+};
+
+struct _GIdlNodeValue
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ gchar *c_name;
+
+ guint32 value;
+};
+
+struct _GIdlNodeConstant
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ GIdlNodeType *type;
+
+ gchar *value;
+};
+
+struct _GIdlNodeEnum
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ gchar *c_name;
+ gchar *init_func;
+
+ GList *values;
+};
+
+struct _GIdlNodeBoxed
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ gchar *c_name;
+ gchar *init_func;
+
+ GList *members;
+};
+
+struct _GIdlNodeStruct
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ gchar *c_name;
+
+ GList *members;
+};
+
+struct _GIdlNodeErrorDomain
+{
+ GIdlNode node;
+
+ gboolean deprecated;
+
+ gchar *name;
+ gchar *getquark;
+ gchar *codes;
+};
+
+
+GIdlNode *g_idl_node_new (GIdlNodeTypeId type);
+void g_idl_node_free (GIdlNode *node);
+guint32 g_idl_node_get_size (GIdlNode *node);
+guint32 g_idl_node_get_full_size (GIdlNode *node);
+void g_idl_node_build_metadata (GIdlNode *node,
+ GIdlModule *module,
+ GList *modules,
+ GHashTable *strings,
+ GHashTable *types,
+ guchar *data,
+ guint32 *offset,
+ guint32 *offset2);
+
+guint32 write_string (const gchar *str,
+ GHashTable *strings,
+ guchar *data,
+ guint32 *offset);
+
+G_END_DECLS
+
+#endif /* __G_IDL_NODE_H__ */
diff --git a/src/gidlparser.c b/src/gidlparser.c
new file mode 100644
index 00000000..8e340db4
--- /dev/null
+++ b/src/gidlparser.c
@@ -0,0 +1,1884 @@
+/* GObject introspection: A parser for the XML IDL 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 <glib.h>
+#include "gidlmodule.h"
+#include "gidlnode.h"
+
+typedef enum
+{
+ STATE_START,
+ STATE_END,
+ STATE_ROOT,
+ STATE_NAMESPACE,
+ STATE_FUNCTION,
+ STATE_PARAMETERS,
+ STATE_OBJECT,
+ STATE_INTERFACE,
+ STATE_IMPLEMENTS,
+ STATE_REQUIRES,
+ STATE_ENUM,
+ STATE_BOXED,
+ STATE_STRUCT,
+ STATE_SIGNAL,
+ STATE_ERRORDOMAIN
+} ParseState;
+
+typedef struct _ParseContext ParseContext;
+struct _ParseContext
+{
+ ParseState state;
+ ParseState prev_state;
+
+ GList *modules;
+
+ GIdlModule *current_module;
+ GIdlNode *current_node;
+};
+
+#define MISSING_ATTRIBUTE(error,element,attribute) \
+ g_set_error (error, \
+ G_MARKUP_ERROR, \
+ G_MARKUP_ERROR_INVALID_CONTENT, \
+ "The attribute '%s' on the element '%s' must be specified", \
+ attribute, element)
+
+static const gchar *
+find_attribute (const gchar *name,
+ const gchar **attribute_names,
+ const gchar **attribute_values)
+{
+ gint i;
+
+ for (i = 0; attribute_names[i] != NULL; i++)
+ if (strcmp (attribute_names[i], name) == 0)
+ return attribute_values[i];
+
+ return 0;
+}
+
+static GIdlNodeType *
+parse_type_internal (gchar *str, gchar **rest)
+{
+ gint i;
+
+ static struct {
+ const gchar *str;
+ gint tag;
+ gboolean pointer;
+ } basic[] = {
+ { "void", 0, 0 },
+ { "gpointer", 0, 1 },
+ { "gboolean", 1, 0 },
+ { "int8_t", 2, 0 },
+ { "int8", 2, 0 },
+ { "gint8", 2, 0 },
+ { "uint8_t", 3, 0 },
+ { "uint8", 3, 0 },
+ { "guint8", 3, 0 },
+ { "int16_t", 4, 0 },
+ { "int16", 4, 0 },
+ { "gint16", 4, 0 },
+ { "uint16_t", 5, 0 },
+ { "uint16", 5, 0 },
+ { "guint16", 5, 0 },
+ { "int32_t", 6, 0 },
+ { "int32", 6, 0 },
+ { "gint32", 6, 0 },
+ { "uint32_t", 7, 0 },
+ { "uint32", 7, 0 },
+ { "guint32", 7, 0 },
+ { "int64_t", 8, 0 },
+ { "int64", 8, 0 },
+ { "gint64", 8, 0 },
+ { "uint64_t", 9, 0 },
+ { "uint64", 9, 0 },
+ { "guint64", 9, 0 },
+ { "float", 10, 0 },
+ { "gfloat", 10, 0 },
+ { "double", 11, 0 },
+ { "gdouble", 11, 0 },
+ { "gchar", 12, 0 },
+ { "char", 12, 0 },
+ { "GString", 13, 0 },
+ { "int", 14, 0 },
+ { "gint", 14, 0 },
+ { "uint", 15, 0 },
+ { "guint", 15, 0 },
+ { "long", 16, 0 },
+ { "glong", 16, 0 },
+ { "ulong", 17, 0 },
+ { "gulong", 17, 0 }
+ };
+
+ gint n_basic = G_N_ELEMENTS (basic);
+ gchar *start, *end;
+
+ GIdlNodeType *type;
+
+ type = (GIdlNodeType *)g_idl_node_new (G_IDL_NODE_TYPE);
+
+ str = g_strstrip (str);
+
+ type->unparsed = g_strdup (str);
+
+ *rest = str;
+ for (i = 0; i < n_basic; i++)
+ {
+ if (g_str_has_prefix (*rest, basic[i].str))
+ {
+ type->is_basic = TRUE;
+ type->tag = basic[i].tag;
+ type->is_pointer = basic[i].pointer;
+
+ *rest += strlen(basic[i].str);
+ *rest = g_strchug (*rest);
+ if (**rest == '*')
+ {
+ type->is_pointer = TRUE;
+ (*rest)++;
+ }
+
+ break;
+ }
+ }
+
+ if (i < n_basic)
+ /* found a basic type */;
+ else if (g_str_has_prefix (*rest, "GList") ||
+ g_str_has_prefix (*rest, "GSList"))
+ {
+ if (g_str_has_prefix (*rest, "GList"))
+ {
+ type->tag = 22;
+ type->is_glist = TRUE;
+ type->is_pointer = TRUE;
+ *rest += strlen ("GList");
+ }
+ else
+ {
+ type->tag = 23;
+ type->is_gslist = TRUE;
+ type->is_pointer = TRUE;
+ *rest += strlen ("GSList");
+ }
+
+ *rest = g_strchug (*rest);
+
+ if (**rest != '<')
+ goto error;
+ (*rest)++;
+
+ type->parameter_type1 = parse_type_internal (*rest, rest);
+ if (type->parameter_type1 == NULL)
+ goto error;
+
+ *rest = g_strchug (*rest);
+
+ if ((*rest)[0] != '>')
+ goto error;
+ (*rest)++;
+ }
+ else if (g_str_has_prefix (*rest, "GHashTable"))
+ {
+ type->tag = 24;
+ type->is_ghashtable = TRUE;
+ type->is_pointer = TRUE;
+ *rest += strlen ("GHashTable");
+
+ *rest = g_strchug (*rest);
+
+ if (**rest != '<')
+ goto error;
+ (*rest)++;
+
+ type->parameter_type1 = parse_type_internal (*rest, rest);
+ if (type->parameter_type1 == NULL)
+ goto error;
+
+ *rest = g_strchug (*rest);
+
+ if ((*rest)[0] != ',')
+ goto error;
+ (*rest)++;
+
+ type->parameter_type2 = parse_type_internal (*rest, rest);
+ if (type->parameter_type2 == NULL)
+ goto error;
+
+ if ((*rest)[0] != '>')
+ goto error;
+ (*rest)++;
+ }
+ else if (g_str_has_prefix (*rest, "GError"))
+ {
+ type->tag = 25;
+ type->is_error = TRUE;
+ type->is_pointer = TRUE;
+ *rest += strlen ("GError");
+
+ *rest = g_strchug (*rest);
+
+ if (**rest != '<')
+ goto error;
+ (*rest)++;
+
+ end = strchr (*rest, '>');
+ str = g_strndup (*rest, end - *rest);
+ type->errors = g_strsplit (str, ",", 0);
+ g_free (str);
+
+ *rest = end + 1;
+ }
+ else
+ {
+ type->tag = 21;
+ type->is_interface = TRUE;
+ start = *rest;
+
+ /* must be an interface type */
+ while (g_ascii_isalnum (**rest) ||
+ **rest == '.' ||
+ **rest == '-' ||
+ **rest == '_' ||
+ **rest == ':')
+ (*rest)++;
+
+ type->interface = g_strndup (start, *rest - start);
+
+ *rest = g_strchug (*rest);
+ if (**rest == '*')
+ {
+ type->is_pointer = TRUE;
+ (*rest)++;
+ }
+ }
+
+ *rest = g_strchug (*rest);
+ if (g_str_has_prefix (*rest, "["))
+ {
+ GIdlNodeType *array;
+
+ array = (GIdlNodeType *)g_idl_node_new (G_IDL_NODE_TYPE);
+
+ array->tag = 20;
+ array->is_pointer = TRUE;
+ array->is_array = TRUE;
+
+ array->parameter_type1 = type;
+
+ array->zero_terminated = FALSE;
+ array->has_length = FALSE;
+ array->length = 0;
+
+ if (!g_str_has_prefix (*rest, "[]"))
+ {
+ gchar *end, *str, **opts;
+
+ end = strchr (*rest, ']');
+ str = g_strndup (*rest + 1, (end - *rest) - 1);
+ opts = g_strsplit (str, ",", 0);
+
+ *rest = end + 1;
+
+ for (i = 0; opts[i]; i++)
+ {
+ gchar **vals;
+
+ vals = g_strsplit (opts[i], "=", 0);
+
+ if (strcmp (vals[0], "zero-terminated") == 0)
+ array->zero_terminated = (strcmp (vals[1], "1") == 0);
+ else if (strcmp (vals[0], "length") == 0)
+ {
+ array->has_length = TRUE;
+ array->length = atoi (vals[1]);
+ }
+
+ g_strfreev (vals);
+ }
+
+ g_free (str);
+ g_strfreev (opts);
+ }
+
+ type = array;
+ }
+
+ return type;
+
+ error:
+ g_idl_node_free ((GIdlNode *)type);
+
+ return NULL;
+}
+
+static GIdlNodeType *
+parse_type (const gchar *type)
+{
+ gchar *str;
+ gchar *rest;
+ GIdlNodeType *node;
+
+ str = g_strdup (type);
+ node = parse_type_internal (str, &rest);
+ g_free (str);
+
+ return node;
+}
+
+static gboolean
+start_boxed (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "boxed") == 0 &&
+ ctx->state == STATE_NAMESPACE)
+ {
+ const gchar *name;
+ const gchar *cname;
+ const gchar *typeinit;
+ const gchar *deprecated;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ cname = find_attribute ("cname", attribute_names, attribute_values);
+ typeinit = find_attribute ("get-type", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (cname == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "cname");
+ else
+ {
+ GIdlNodeBoxed *boxed;
+
+ boxed = (GIdlNodeBoxed *) g_idl_node_new (G_IDL_NODE_BOXED);
+
+ ((GIdlNode *)boxed)->name = g_strdup (name);
+ boxed->c_name = g_strdup (cname);
+ boxed->init_func = g_strdup (typeinit);
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ boxed->deprecated = TRUE;
+ else
+ boxed->deprecated = FALSE;
+
+ ctx->current_node = (GIdlNode *)boxed;
+ ctx->current_module->entries =
+ g_list_append (ctx->current_module->entries, boxed);
+
+ ctx->state = STATE_BOXED;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+start_function (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if ((ctx->state == STATE_NAMESPACE &&
+ (strcmp (element_name, "function") == 0 ||
+ strcmp (element_name, "callback") == 0)) ||
+ ((ctx->state == STATE_OBJECT ||
+ ctx->state == STATE_INTERFACE ||
+ ctx->state == STATE_BOXED ||
+ ctx->state == STATE_STRUCT) &&
+ strcmp (element_name, "method") == 0) ||
+ (ctx->state == STATE_OBJECT &&
+ strcmp (element_name, "constructor") == 0))
+ {
+ const gchar *name;
+ const gchar *cname;
+ const gchar *deprecated;
+ const gchar *type;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ cname = find_attribute ("cname", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+ type = find_attribute ("type", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (strcmp (element_name, "callback") != 0 && cname == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "cname");
+ else
+ {
+ GIdlNodeFunction *function;
+
+ function = (GIdlNodeFunction *) g_idl_node_new (G_IDL_NODE_FUNCTION);
+
+ ((GIdlNode *)function)->name = g_strdup (name);
+ function->c_name = g_strdup (cname);
+ function->parameters = NULL;
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ function->deprecated = TRUE;
+ else
+ function->deprecated = FALSE;
+
+ if (strcmp (element_name, "method") == 0 ||
+ strcmp (element_name, "constructor") == 0)
+ {
+ function->is_method = TRUE;
+
+ if (type && strcmp (type, "setter") == 0)
+ function->is_setter = TRUE;
+ else if (type && strcmp (type, "getter") == 0)
+ function->is_getter = TRUE;
+
+ if (strcmp (element_name, "constructor") == 0)
+ function->is_constructor = TRUE;
+ else
+ function->is_constructor = FALSE;
+ }
+ else
+ {
+ function->is_method = FALSE;
+ function->is_setter = FALSE;
+ function->is_getter = FALSE;
+ function->is_constructor = FALSE;
+ if (strcmp (element_name, "callback") == 0)
+ ((GIdlNode *)function)->type = G_IDL_NODE_CALLBACK;
+ }
+
+ if (ctx->current_node == NULL)
+ {
+ ctx->current_module->entries =
+ g_list_append (ctx->current_module->entries, function);
+ }
+ else
+ switch (ctx->current_node->type)
+ {
+ case G_IDL_NODE_INTERFACE:
+ {
+ GIdlNodeInterface *iface;
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface->members = g_list_append (iface->members, function);
+ }
+ break;
+ case G_IDL_NODE_BOXED:
+ {
+ GIdlNodeBoxed *boxed;
+
+ boxed = (GIdlNodeBoxed *)ctx->current_node;
+ boxed->members = g_list_append (boxed->members, function);
+ }
+ break;
+ case G_IDL_NODE_STRUCT:
+ {
+ GIdlNodeStruct *struct_;
+
+ struct_ = (GIdlNodeStruct *)ctx->current_node;
+ struct_->members = g_list_append (struct_->members, function); }
+ break;
+ }
+
+ ctx->current_node = (GIdlNode *)function;
+ ctx->state = STATE_FUNCTION;
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean
+start_parameter (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "parameter") == 0 &&
+ ctx->state == STATE_PARAMETERS)
+ {
+ const gchar *type;
+ const gchar *name;
+ const gchar *direction;
+ const gchar *retval;
+ const gchar *dipper;
+ const gchar *optional;
+ const gchar *nullok;
+ const gchar *transfer;
+
+ type = find_attribute ("type", attribute_names, attribute_values);
+ name = find_attribute ("name", attribute_names, attribute_values);
+ direction = find_attribute ("direction", attribute_names, attribute_values);
+ retval = find_attribute ("retval", attribute_names, attribute_values);
+ dipper = find_attribute ("dipper", attribute_names, attribute_values);
+ optional = find_attribute ("optional", attribute_names, attribute_values);
+ nullok = find_attribute ("null-ok", attribute_names, attribute_values);
+ transfer = find_attribute ("transfer", attribute_names, attribute_values);
+
+ if (type == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "type");
+ else if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else
+ {
+ GIdlNodeParam *param;
+
+ param = (GIdlNodeParam *)g_idl_node_new (G_IDL_NODE_PARAM);
+
+ if (direction && strcmp (direction, "out") == 0)
+ {
+ param->in = FALSE;
+ param->out = TRUE;
+ }
+ else if (direction && strcmp (direction, "inout") == 0)
+ {
+ param->in = TRUE;
+ param->out = TRUE;
+ }
+ else
+ {
+ param->in = TRUE;
+ param->out = FALSE;
+ }
+
+ if (retval && strcmp (retval, "1") == 0)
+ param->retval = TRUE;
+ else
+ param->retval = FALSE;
+
+ if (dipper && strcmp (dipper, "1") == 0)
+ param->dipper = TRUE;
+ else
+ param->dipper = FALSE;
+
+ if (optional && strcmp (optional, "1") == 0)
+ param->optional = TRUE;
+ else
+ param->optional = FALSE;
+
+ if (nullok && strcmp (nullok, "1") == 0)
+ param->null_ok = TRUE;
+ else
+ param->null_ok = FALSE;
+
+ if (transfer && strcmp (transfer, "none") == 0)
+ {
+ param->transfer = FALSE;
+ param->shallow_transfer = FALSE;
+ }
+ else if (transfer && strcmp (transfer, "shallow") == 0)
+ {
+ param->transfer = FALSE;
+ param->shallow_transfer = TRUE;
+ }
+ else
+ {
+ param->transfer = TRUE;
+ param->shallow_transfer = FALSE;
+ }
+
+ ((GIdlNode *)param)->name = g_strdup (name);
+ param->type = parse_type (type);
+
+ switch (ctx->current_node->type)
+ {
+ case G_IDL_NODE_FUNCTION:
+ case G_IDL_NODE_CALLBACK:
+ {
+ GIdlNodeFunction *func;
+
+ func = (GIdlNodeFunction *)ctx->current_node;
+ func->parameters = g_list_append (func->parameters, param);
+ }
+ break;
+ case G_IDL_NODE_SIGNAL:
+ {
+ GIdlNodeSignal *signal;
+
+ signal = (GIdlNodeSignal *)ctx->current_node;
+ signal->parameters = g_list_append (signal->parameters, param);
+ }
+ break;
+ case G_IDL_NODE_VFUNC:
+ {
+ GIdlNodeVFunc *vfunc;
+
+ vfunc = (GIdlNodeVFunc *)ctx->current_node;
+ vfunc->parameters = g_list_append (vfunc->parameters, param);
+ }
+ break;
+ }
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+start_field (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "field") == 0 &&
+ (ctx->state == STATE_OBJECT ||
+ ctx->state == STATE_BOXED ||
+ ctx->state == STATE_STRUCT))
+ {
+ const gchar *cname;
+ const gchar *type;
+ const gchar *readable;
+ const gchar *writable;
+ const gchar *bits;
+
+ cname = find_attribute ("cname", attribute_names, attribute_values);
+ type = find_attribute ("type", attribute_names, attribute_values);
+ readable = find_attribute ("readable", attribute_names, attribute_values);
+ writable = find_attribute ("writable", attribute_names, attribute_values);
+ bits = find_attribute ("bits", attribute_names, attribute_values);
+
+ if (cname == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "cname");
+ else if (type == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "type");
+ else
+ {
+ GIdlNodeField *field;
+
+ field = (GIdlNodeField *)g_idl_node_new (G_IDL_NODE_FIELD);
+ field->c_name = g_strdup (cname);
+ if (readable && strcmp (readable, "1") == 0)
+ field->readable = TRUE;
+ else
+ field->readable = FALSE;
+
+ if (writable && strcmp (writable, "1") == 0)
+ field->writable = TRUE;
+ else
+ field->writable = FALSE;
+
+ if (bits)
+ field->bits = atoi (bits);
+ else
+ field->bits = 0;
+
+ field->type = parse_type (type);
+
+ switch (ctx->current_node->type)
+ {
+ case G_IDL_NODE_INTERFACE:
+ {
+ GIdlNodeInterface *iface;
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface->members = g_list_append (iface->members, field);
+ }
+ break;
+ case G_IDL_NODE_BOXED:
+ {
+ GIdlNodeBoxed *boxed;
+
+ boxed = (GIdlNodeBoxed *)ctx->current_node;
+ boxed->members = g_list_append (boxed->members, field);
+ }
+ break;
+ case G_IDL_NODE_STRUCT:
+ {
+ GIdlNodeStruct *struct_;
+
+ struct_ = (GIdlNodeStruct *)ctx->current_node;
+ struct_->members = g_list_append (struct_->members, field);
+ }
+ break;
+ }
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+start_enum (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if ((strcmp (element_name, "enum") == 0 && ctx->state == STATE_NAMESPACE) ||
+ (strcmp (element_name, "flags") == 0 && ctx->state == STATE_NAMESPACE))
+ {
+ const gchar *name;
+ const gchar *cname;
+ const gchar *type;
+ const gchar *typeinit;
+ const gchar *deprecated;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ cname = find_attribute ("cname", attribute_names, attribute_values);
+ typeinit = find_attribute ("get-type", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (cname == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "cname");
+ else
+ {
+ GIdlNodeEnum *enum_;
+
+ if (strcmp (element_name, "enum") == 0)
+ enum_ = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_ENUM);
+ else
+ enum_ = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_FLAGS);
+ ((GIdlNode *)enum_)->name = g_strdup (name);
+ enum_->c_name = g_strdup (cname);
+ enum_->init_func = g_strdup (typeinit);
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ enum_->deprecated = TRUE;
+ else
+ enum_->deprecated = FALSE;
+
+ ctx->current_node = (GIdlNode *) enum_;
+ ctx->current_module->entries =
+ g_list_append (ctx->current_module->entries, enum_);
+
+ ctx->state = STATE_ENUM;
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+start_property (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "property") == 0 &&
+ (ctx->state == STATE_OBJECT ||
+ ctx->state == STATE_INTERFACE))
+ {
+ const gchar *name;
+ const gchar *cname;
+ const gchar *type;
+ const gchar *readable;
+ const gchar *writable;
+ const gchar *construct;
+ const gchar *construct_only;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ cname = find_attribute ("cname", attribute_names, attribute_values);
+ type = find_attribute ("type", attribute_names, attribute_values);
+ readable = find_attribute ("readable", attribute_names, attribute_values);
+ writable = find_attribute ("writable", attribute_names, attribute_values);
+ construct = find_attribute ("construct", attribute_names, attribute_values);
+ construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (type == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "type");
+ else
+ {
+ GIdlNodeProperty *property;
+ GIdlNodeInterface *iface;
+
+ property = (GIdlNodeProperty *) g_idl_node_new (G_IDL_NODE_PROPERTY);
+
+ ((GIdlNode *)property)->name = g_strdup (name);
+ property->c_name = g_strdup (cname);
+
+ if (readable && strcmp (readable, "1") == 0)
+ property->readable = TRUE;
+ else
+ property->readable = FALSE;
+ if (writable && strcmp (writable, "1") == 0)
+ property->writable = TRUE;
+ else
+ property->writable = FALSE;
+ if (construct && strcmp (construct, "1") == 0)
+ property->construct = TRUE;
+ else
+ property->construct = FALSE;
+ if (construct_only && strcmp (construct_only, "1") == 0)
+ property->construct_only = TRUE;
+ else
+ property->construct_only = FALSE;
+
+ property->type = parse_type (type);
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface->members = g_list_append (iface->members, property);
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gint
+parse_value (const gchar *str)
+{
+ gchar *shift_op;
+
+ /* FIXME just a quick hack */
+ shift_op = strstr (str, "<<");
+
+ if (shift_op)
+ {
+ gint base, shift;
+
+ base = strtol (str, NULL, 10);
+ shift = strtol (shift_op + 3, NULL, 10);
+
+ return base << shift;
+ }
+ else
+ return strtol (str, NULL, 10);
+
+ return 0;
+}
+
+static gboolean
+start_member (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "member") == 0 &&
+ ctx->state == STATE_ENUM)
+ {
+ const gchar *name;
+ const gchar *cname;
+ const gchar *value;
+ const gchar *deprecated;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ cname = find_attribute ("cname", attribute_names, attribute_values);
+ value = find_attribute ("value", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (cname == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "cname");
+ else
+ {
+ GIdlNodeEnum *enum_;
+ GIdlNodeValue *value_;
+
+ value_ = (GIdlNodeValue *) g_idl_node_new (G_IDL_NODE_VALUE);
+
+ ((GIdlNode *)value_)->name = g_strdup (name);
+ value_->c_name = g_strdup (cname);
+
+ value_->value = parse_value (value);
+
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ value_->deprecated = TRUE;
+ else
+ value_->deprecated = FALSE;
+
+ enum_ = (GIdlNodeEnum *)ctx->current_node;
+ enum_->values = g_list_append (enum_->values, value_);
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+start_constant (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "constant") == 0 &&
+ (ctx->state == STATE_NAMESPACE ||
+ ctx->state == STATE_OBJECT ||
+ ctx->state == STATE_INTERFACE))
+ {
+ const gchar *name;
+ const gchar *type;
+ const gchar *value;
+ const gchar *deprecated;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ type = find_attribute ("type", attribute_names, attribute_values);
+ value = find_attribute ("value", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (type == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "type");
+ else if (value == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "value");
+ else
+ {
+ GIdlNodeConstant *constant;
+
+ constant = (GIdlNodeConstant *) g_idl_node_new (G_IDL_NODE_CONSTANT);
+
+ ((GIdlNode *)constant)->name = g_strdup (name);
+ constant->value = g_strdup (value);
+
+ constant->type = parse_type (type);
+
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ constant->deprecated = TRUE;
+ else
+ constant->deprecated = FALSE;
+
+ if (ctx->state == STATE_NAMESPACE)
+ {
+ ctx->current_node = (GIdlNode *) constant;
+ ctx->current_module->entries =
+ g_list_append (ctx->current_module->entries, constant);
+ }
+ else
+ {
+ GIdlNodeInterface *iface;
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface->members = g_list_append (iface->members, constant);
+ }
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+start_errordomain (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "errordomain") == 0 &&
+ ctx->state == STATE_NAMESPACE)
+ {
+ const gchar *name;
+ const gchar *getquark;
+ const gchar *codes;
+ const gchar *deprecated;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ getquark = find_attribute ("get-quark", attribute_names, attribute_values);
+ codes = find_attribute ("codes", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (getquark == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "getquark");
+ else if (codes == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "codes");
+ else
+ {
+ GIdlNodeErrorDomain *domain;
+
+ domain = (GIdlNodeErrorDomain *) g_idl_node_new (G_IDL_NODE_ERROR_DOMAIN);
+
+ ((GIdlNode *)domain)->name = g_strdup (name);
+ domain->getquark = g_strdup (getquark);
+ domain->codes = g_strdup (codes);
+
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ domain->deprecated = TRUE;
+ else
+ domain->deprecated = FALSE;
+
+ ctx->current_node = (GIdlNode *) domain;
+ ctx->current_module->entries =
+ g_list_append (ctx->current_module->entries, domain);
+
+ ctx->state = STATE_ERRORDOMAIN;
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+start_interface (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "interface") == 0 &&
+ ctx->state == STATE_NAMESPACE)
+ {
+ const gchar *name;
+ const gchar *cname;
+ const gchar *typeinit;
+ const gchar *deprecated;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ cname = find_attribute ("cname", attribute_names, attribute_values);
+ typeinit = find_attribute ("get-type", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (cname == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "cname");
+ else
+ {
+ GIdlNodeInterface *iface;
+
+ iface = (GIdlNodeInterface *) g_idl_node_new (G_IDL_NODE_INTERFACE);
+ ((GIdlNode *)iface)->name = g_strdup (name);
+ iface->c_name = g_strdup (cname);
+ iface->init_func = g_strdup (typeinit);
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ iface->deprecated = TRUE;
+ else
+ iface->deprecated = FALSE;
+
+ ctx->current_node = (GIdlNode *) iface;
+ ctx->current_module->entries =
+ g_list_append (ctx->current_module->entries, iface);
+
+ ctx->state = STATE_INTERFACE;
+
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+start_object (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "object") == 0 &&
+ ctx->state == STATE_NAMESPACE)
+ {
+ const gchar *name;
+ const gchar *cname;
+ const gchar *parent;
+ const gchar *typeinit;
+ const gchar *deprecated;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ cname = find_attribute ("cname", attribute_names, attribute_values);
+ parent = find_attribute ("parent", attribute_names, attribute_values);
+ typeinit = find_attribute ("get-type", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (cname == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "cname");
+ else
+ {
+ GIdlNodeInterface *iface;
+
+ iface = (GIdlNodeInterface *) g_idl_node_new (G_IDL_NODE_OBJECT);
+ ((GIdlNode *)iface)->name = g_strdup (name);
+ iface->c_name = g_strdup (cname);
+ iface->init_func = g_strdup (typeinit);
+ iface->parent = g_strdup (parent);
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ iface->deprecated = TRUE;
+ else
+ iface->deprecated = FALSE;
+
+ ctx->current_node = (GIdlNode *) iface;
+ ctx->current_module->entries =
+ g_list_append (ctx->current_module->entries, iface);
+
+ ctx->state = STATE_OBJECT;
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+start_return_type (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "return-type") == 0 &&
+ ctx->state == STATE_FUNCTION)
+ {
+ const gchar *type;
+ const gchar *nullok;
+ const gchar *transfer;
+
+ type = find_attribute ("type", attribute_names, attribute_values);
+ nullok = find_attribute ("null-ok", attribute_names, attribute_values);
+ transfer = find_attribute ("transfer", attribute_names, attribute_values);
+ if (type == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "type");
+ else
+ {
+ GIdlNodeParam *param;
+
+ param = (GIdlNodeParam *)g_idl_node_new (G_IDL_NODE_PARAM);
+ param->in = FALSE;
+ param->out = FALSE;
+ param->retval = TRUE;
+ if (nullok && strcmp (nullok, "1") == 0)
+ param->null_ok = TRUE;
+ else
+ param->null_ok = FALSE;
+ if (transfer && strcmp (transfer, "none") == 0)
+ {
+ param->transfer = FALSE;
+ param->shallow_transfer = FALSE;
+ }
+ else if (transfer && strcmp (transfer, "shallow") == 0)
+ {
+ param->transfer = FALSE;
+ param->shallow_transfer = TRUE;
+ }
+ else
+ {
+ param->transfer = TRUE;
+ param->shallow_transfer = FALSE;
+ }
+
+ param->type = parse_type (type);
+
+ switch (ctx->current_node->type)
+ {
+ case G_IDL_NODE_FUNCTION:
+ case G_IDL_NODE_CALLBACK:
+ {
+ GIdlNodeFunction *func = (GIdlNodeFunction *)ctx->current_node;
+ func->result = param;
+ }
+ break;
+ case G_IDL_NODE_SIGNAL:
+ {
+ GIdlNodeSignal *signal = (GIdlNodeSignal *)ctx->current_node;
+ signal->result = param;
+ }
+ break;
+ case G_IDL_NODE_VFUNC:
+ {
+ GIdlNodeVFunc *vfunc = (GIdlNodeVFunc *)ctx->current_node;
+ vfunc->result = param;
+ }
+ break;
+ }
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+start_signal (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "signal") == 0 &&
+ (ctx->state == STATE_OBJECT ||
+ ctx->state == STATE_INTERFACE))
+ {
+ const gchar *name;
+ const gchar *cname;
+ const gchar *when;
+ const gchar *no_recurse;
+ const gchar *detailed;
+ const gchar *action;
+ const gchar *no_hooks;
+ const gchar *has_class_closure;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ cname = find_attribute ("cname", attribute_names, attribute_values);
+ when = find_attribute ("when", attribute_names, attribute_values);
+ no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
+ detailed = find_attribute ("detailed", attribute_names, attribute_values);
+ action = find_attribute ("action", attribute_names, attribute_values);
+ no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
+ has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (when == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "when");
+ else
+ {
+ GIdlNodeInterface *iface;
+ GIdlNodeSignal *signal;
+
+ signal = (GIdlNodeSignal *)g_idl_node_new (G_IDL_NODE_SIGNAL);
+
+ ((GIdlNode *)signal)->name = g_strdup (name);
+ signal->c_name = g_strdup (cname);
+
+ signal->run_first = FALSE;
+ signal->run_last = FALSE;
+ signal->run_cleanup = FALSE;
+ if (strcmp (when, "FIRST") == 0)
+ signal->run_first = TRUE;
+ else if (strcmp (when, "LAST") == 0)
+ signal->run_last = TRUE;
+ else
+ signal->run_cleanup = TRUE;
+
+ if (no_recurse && strcmp (no_recurse, "1") == 0)
+ signal->no_recurse = TRUE;
+ else
+ signal->no_recurse = FALSE;
+ if (detailed && strcmp (detailed, "1") == 0)
+ signal->detailed = TRUE;
+ else
+ signal->detailed = FALSE;
+ if (action && strcmp (action, "1") == 0)
+ signal->action = TRUE;
+ else
+ signal->action = FALSE;
+ if (no_hooks && strcmp (no_hooks, "1") == 0)
+ signal->no_hooks = TRUE;
+ else
+ signal->no_hooks = FALSE;
+ if (has_class_closure && strcmp (has_class_closure, "1") == 0)
+ signal->has_class_closure = TRUE;
+ else
+ signal->has_class_closure = FALSE;
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface->members = g_list_append (iface->members, signal);
+
+ ctx->current_node = (GIdlNode *)signal;
+ ctx->state = STATE_FUNCTION;
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+start_vfunc (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "vfunc") == 0 &&
+ (ctx->state == STATE_OBJECT ||
+ ctx->state == STATE_INTERFACE))
+ {
+ const gchar *name;
+ const gchar *cname;
+ const gchar *must_chain_up;
+ const gchar *override;
+ const gchar *is_class_closure;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ cname = find_attribute ("cname", attribute_names, attribute_values);
+ must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);
+ override = find_attribute ("override", attribute_names, attribute_values);
+ is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else
+ {
+ GIdlNodeInterface *iface;
+ GIdlNodeVFunc *vfunc;
+
+ vfunc = (GIdlNodeVFunc *)g_idl_node_new (G_IDL_NODE_VFUNC);
+
+ ((GIdlNode *)vfunc)->name = g_strdup (name);
+ vfunc->c_name = g_strdup (cname);
+
+ if (must_chain_up && strcmp (must_chain_up, "1") == 0)
+ vfunc->must_chain_up = TRUE;
+ else
+ vfunc->must_chain_up = FALSE;
+
+ if (override && strcmp (override, "always") == 0)
+ {
+ vfunc->must_be_implemented = TRUE;
+ vfunc->must_not_be_implemented = FALSE;
+ }
+ else if (override && strcmp (override, "never") == 0)
+ {
+ vfunc->must_be_implemented = FALSE;
+ vfunc->must_not_be_implemented = TRUE;
+ }
+ else
+ {
+ vfunc->must_be_implemented = FALSE;
+ vfunc->must_not_be_implemented = FALSE;
+ }
+
+ if (is_class_closure && strcmp (is_class_closure, "1") == 0)
+ vfunc->is_class_closure = TRUE;
+ else
+ vfunc->is_class_closure = FALSE;
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface->members = g_list_append (iface->members, vfunc);
+
+ ctx->current_node = (GIdlNode *)vfunc;
+ ctx->state = STATE_FUNCTION;
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static gboolean
+start_struct (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error)
+{
+ if (strcmp (element_name, "struct") == 0 &&
+ ctx->state == STATE_NAMESPACE)
+ {
+ const gchar *name;
+ const gchar *cname;
+ const gchar *deprecated;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+ cname = find_attribute ("cname", attribute_names, attribute_values);
+ deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else if (cname == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "cname");
+ else
+ {
+ GIdlNodeStruct *struct_;
+
+ struct_ = (GIdlNodeStruct *) g_idl_node_new (G_IDL_NODE_STRUCT);
+
+ ((GIdlNode *)struct_)->name = g_strdup (name);
+ struct_->c_name = g_strdup (cname);
+ if (deprecated && strcmp (deprecated, "1") == 0)
+ struct_->deprecated = TRUE;
+ else
+ struct_->deprecated = FALSE;
+
+ ctx->current_node = (GIdlNode *)struct_;
+ ctx->current_module->entries =
+ g_list_append (ctx->current_module->entries, struct_);
+
+ ctx->state = STATE_STRUCT;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+start_element_handler (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error)
+{
+ ParseContext *ctx = user_data;
+ gint i, line_number, char_number;
+
+ switch (element_name[0])
+ {
+ case 'a':
+ if (strcmp (element_name, "api") == 0 && ctx->state == STATE_START)
+ {
+ const gchar *version;
+
+ version = find_attribute ("version", attribute_names, attribute_values);
+
+ if (version == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "version");
+ else if (strcmp (version, "1.0") != 0)
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Unsupported version '%s'",
+ version);
+ else
+ ctx->state = STATE_ROOT;
+
+ goto out;
+ }
+ break;
+
+ case 'b':
+ if (start_boxed (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ break;
+
+ case 'c':
+ if (start_function (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (start_constant (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ break;
+
+ case 'e':
+ if (start_enum (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (start_errordomain (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ break;
+
+ case 'f':
+ if (start_function (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (start_field (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (start_enum (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+
+ break;
+
+ case 'i':
+ if (start_interface (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ if (strcmp (element_name, "implements") == 0 &&
+ ctx->state == STATE_OBJECT)
+ {
+ ctx->state = STATE_IMPLEMENTS;
+
+ goto out;
+ }
+ else if (strcmp (element_name, "interface") == 0 &&
+ ctx->state == STATE_IMPLEMENTS)
+ {
+ const gchar *cname;
+
+ cname = find_attribute ("name", attribute_names, attribute_values);
+
+ if (cname == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else
+ {
+ GIdlNodeInterface *iface;
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface ->interfaces = g_list_append (iface->interfaces, g_strdup (cname));
+ }
+
+ goto out;
+ }
+ else if (strcmp (element_name, "interface") == 0 &&
+ ctx->state == STATE_REQUIRES)
+ {
+ const gchar *cname;
+
+ cname = find_attribute ("name", attribute_names, attribute_values);
+
+ if (cname == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else
+ {
+ GIdlNodeInterface *iface;
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (cname));
+ }
+
+ goto out;
+ }
+ break;
+
+ case 'm':
+ if (start_function (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (start_member (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ break;
+
+ case 'n':
+ if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_ROOT)
+ {
+ const gchar *name;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+
+ if (name == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "name");
+ else
+ {
+ ctx->current_module = g_idl_module_new (name);
+ ctx->modules = g_list_append (ctx->modules, ctx->current_module);
+
+ ctx->state = STATE_NAMESPACE;
+ }
+
+ goto out;
+ }
+ break;
+
+ case 'o':
+ if (start_object (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (strcmp (element_name, "object") == 0 &&
+ ctx->state == STATE_REQUIRES)
+ {
+ const gchar *cname;
+
+ cname = find_attribute ("cname", attribute_names, attribute_values);
+
+ if (cname == NULL)
+ MISSING_ATTRIBUTE (error, element_name, "cname");
+ else
+ {
+ GIdlNodeInterface *iface;
+
+ iface = (GIdlNodeInterface *)ctx->current_node;
+ iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (cname));
+ }
+
+ goto out;
+ }
+ break;
+
+ case 'p':
+ if (start_property (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (strcmp (element_name, "parameters") == 0 &&
+ ctx->state == STATE_FUNCTION)
+ {
+ ctx->state = STATE_PARAMETERS;
+
+ goto out;
+ }
+ else if (start_parameter (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+
+ break;
+
+ case 'r':
+ if (start_return_type (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (strcmp (element_name, "requires") == 0 &&
+ ctx->state == STATE_INTERFACE)
+ {
+ ctx->state = STATE_REQUIRES;
+
+ goto out;
+ }
+
+ break;
+
+ case 's':
+ if (start_signal (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ else if (start_struct (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+
+ break;
+
+ case 'v':
+ if (start_vfunc (context, element_name,
+ attribute_names, attribute_values,
+ ctx, error))
+ goto out;
+ break;
+ }
+
+ g_markup_parse_context_get_position (context, &line_number, &char_number);
+
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+ "Unexpected start tag '%s' on line %d char %d",
+ element_name,
+ line_number, char_number);
+
+ out: ;
+
+}
+
+static void
+end_element_handler (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{
+ ParseContext *ctx = user_data;
+
+ switch (ctx->state)
+ {
+ case STATE_START:
+ case STATE_END:
+ /* no need to GError here, GMarkup already catches this */
+ break;
+
+ case STATE_ROOT:
+ ctx->state = STATE_END;
+ break;
+
+ case STATE_NAMESPACE:
+ ctx->current_module = NULL;
+ ctx->state = STATE_ROOT;
+ break;
+
+ case STATE_FUNCTION:
+ if (strcmp (element_name, "return-type") == 0)
+ /* do nothing */ ;
+
+ else if (ctx->current_node == g_list_last (ctx->current_module->entries)->data)
+ {
+ ctx->current_node = NULL;
+ ctx->state = STATE_NAMESPACE;
+ }
+ else
+ {
+ ctx->current_node = g_list_last (ctx->current_module->entries)->data;
+ if (ctx->current_node->type == G_IDL_NODE_INTERFACE)
+ ctx->state = STATE_INTERFACE;
+ else if (ctx->current_node->type == G_IDL_NODE_OBJECT)
+ ctx->state = STATE_OBJECT;
+ else if (ctx->current_node->type == G_IDL_NODE_BOXED)
+ ctx->state = STATE_BOXED;
+ else if (ctx->current_node->type == G_IDL_NODE_STRUCT)
+ ctx->state = STATE_STRUCT;
+ }
+ break;
+
+ case STATE_OBJECT:
+ if (strcmp (element_name, "object") == 0)
+ {
+ ctx->current_node = NULL;
+ ctx->state = STATE_NAMESPACE;
+ }
+ break;
+
+ case STATE_ERRORDOMAIN:
+ if (strcmp (element_name, "errordomain") == 0)
+ {
+ ctx->current_node = NULL;
+ ctx->state = STATE_NAMESPACE;
+ }
+ break;
+
+ case STATE_INTERFACE:
+ if (strcmp (element_name, "interface") == 0)
+ {
+ ctx->current_node = NULL;
+ ctx->state = STATE_NAMESPACE;
+ }
+ break;
+
+ case STATE_ENUM:
+ if (strcmp (element_name, "enum") == 0 ||
+ strcmp (element_name, "flags") == 0)
+ {
+ ctx->current_node = NULL;
+ ctx->state = STATE_NAMESPACE;
+ }
+ break;
+
+ case STATE_BOXED:
+ if (strcmp (element_name, "boxed") == 0)
+ {
+ ctx->current_node = NULL;
+ ctx->state = STATE_NAMESPACE;
+ }
+ break;
+
+ case STATE_STRUCT:
+ if (strcmp (element_name, "struct") == 0)
+ {
+ ctx->current_node = NULL;
+ ctx->state = STATE_NAMESPACE;
+ }
+ break;
+ case STATE_IMPLEMENTS:
+ ctx->state = STATE_OBJECT;
+ break;
+ case STATE_REQUIRES:
+ ctx->state = STATE_INTERFACE;
+ break;
+ case STATE_PARAMETERS:
+ if (strcmp (element_name, "parameters") == 0)
+ ctx->state = STATE_FUNCTION;
+ break;
+ default:
+ g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
+ }
+}
+
+static void
+text_handler (GMarkupParseContext *context,
+ const gchar *text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{
+ /* FIXME warn about non-whitespace text */
+}
+
+static void
+cleanup (GMarkupParseContext *context,
+ GError *error,
+ gpointer user_data)
+{
+ ParseContext *ctx = user_data;
+ GList *m;
+
+ for (m = ctx->modules; m; m = m->next)
+ g_idl_module_free (m->data);
+ g_list_free (ctx->modules);
+ ctx->modules = NULL;
+
+ ctx->current_module = NULL;
+}
+
+static GMarkupParser parser =
+{
+ start_element_handler,
+ end_element_handler,
+ text_handler,
+ NULL,
+ cleanup
+};
+
+GList *
+g_idl_parse_string (const gchar *buffer,
+ gssize length,
+ GError **error)
+{
+ ParseContext ctx = { 0 };
+ GMarkupParseContext *context;
+
+ ctx.state = STATE_START;
+
+ context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
+ if (!g_markup_parse_context_parse (context, buffer, length, error))
+ goto out;
+
+ if (!g_markup_parse_context_end_parse (context, error))
+ goto out;
+
+ out:
+
+ g_markup_parse_context_free (context);
+
+ return ctx.modules;
+}
+
+GList *
+g_idl_parse_file (const gchar *filename,
+ GError **error)
+{
+ gchar *buffer;
+ gssize length;
+ GList *modules;
+
+ if (!g_file_get_contents (filename, &buffer, &length, error))
+ return NULL;
+
+ modules = g_idl_parse_string (buffer, length, error);
+
+ g_free (buffer);
+
+ return modules;
+}
+
+
diff --git a/src/gidlparser.h b/src/gidlparser.h
new file mode 100644
index 00000000..2d71aaa0
--- /dev/null
+++ b/src/gidlparser.h
@@ -0,0 +1,38 @@
+/* GObject introspection: A parser for the XML IDL 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.
+ */
+
+#ifndef __G_IDL_PARSER_H__
+#define __G_IDL_PARSER_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+
+GList *g_idl_parse_string (const gchar *buffer,
+ gssize length,
+ GError **error);
+GList *g_idl_parse_file (const gchar *filename,
+ GError **error);
+
+
+G_END_DECLS
+
+#endif /* __G_IDL_PARSER_H__ */
diff --git a/src/ginfo.c b/src/ginfo.c
new file mode 100644
index 00000000..5c9f6a14
--- /dev/null
+++ b/src/ginfo.c
@@ -0,0 +1,1639 @@
+/* GObject introspection: Repository implementation
+ *
+ * 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 <glib.h>
+#include <glib-object.h>
+
+#include "girepository.h"
+#include "gmetadata.h"
+
+struct _GIBaseInfo
+{
+ gint type;
+ gint ref_count;
+ GIBaseInfo *container;
+
+ const guchar *metadata;
+ guint32 offset;
+};
+
+struct _GIUnresolvedInfo
+{
+ gint type;
+ gint ref_count;
+ GIBaseInfo *container;
+
+ const gchar *name;
+ const gchar *namespace;
+};
+
+struct _GICallableInfo
+{
+ GIBaseInfo base;
+};
+
+struct _GIFunctionInfo
+{
+ GICallableInfo callable;
+};
+
+struct _GICallbackInfo
+{
+ GICallableInfo callable;
+};
+
+struct _GIRegisteredTypeInfo
+{
+ GIBaseInfo base;
+};
+
+struct _GIStructInfo
+{
+ GIRegisteredTypeInfo registered;
+};
+
+struct _GIEnumInfo
+{
+ GIRegisteredTypeInfo registered;
+};
+
+struct _GIObjectInfo
+{
+ GIRegisteredTypeInfo registered;
+};
+
+struct _GIInterfaceInfo
+{
+ GIRegisteredTypeInfo registered;
+};
+
+struct _GIConstantInfo
+{
+ GIBaseInfo base;
+};
+
+struct _GIValueInfo
+{
+ GIBaseInfo base;
+};
+
+struct _GISignalInfo
+{
+ GICallableInfo callable;
+};
+
+struct _GIVFuncInfo
+{
+ GICallableInfo callable;
+};
+
+struct _GIPropertyInfo
+{
+ GIBaseInfo base;
+};
+
+struct _GIFieldInfo
+{
+ GIBaseInfo base;
+};
+
+struct _GIArgInfo
+{
+ GIBaseInfo base;
+};
+
+
+struct _GITypeInfo
+{
+ GIBaseInfo base;
+};
+
+
+/* info creation */
+GIBaseInfo *
+g_info_new (GIInfoType type,
+ GIBaseInfo *container,
+ const guchar *metadata,
+ guint32 offset)
+{
+ GIBaseInfo *info;
+
+ info = g_new0 (GIBaseInfo, 1);
+
+ info->ref_count = 1;
+ info->type = type;
+
+ info->metadata = metadata;
+ info->offset = offset;
+
+ if (container)
+ info->container = g_base_info_ref (container);
+
+ return info;
+}
+
+static GIBaseInfo *
+g_info_from_entry (const guchar *metadata,
+ guint16 index)
+{
+ GIBaseInfo *result;
+ DirEntry *entry = g_metadata_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);
+
+ GIRepository *repository = g_irepository_get_default ();
+
+ result = g_irepository_find_by_name (repository, namespace, name);
+ if (result == NULL)
+ {
+ GIUnresolvedInfo *unresolved;
+
+ unresolved = g_new0 (GIUnresolvedInfo, 1);
+
+ unresolved->type = GI_INFO_TYPE_UNRESOLVED;
+ unresolved->ref_count = 1;
+ unresolved->container = NULL;
+ unresolved->name = name;
+ unresolved->namespace = namespace;
+
+ result = (GIBaseInfo*)unresolved;
+ }
+ }
+
+ return result;
+}
+
+/* GIBaseInfo functions */
+GIBaseInfo *
+g_base_info_ref (GIBaseInfo *info)
+{
+ info->ref_count++;
+
+ return info;
+}
+
+void
+g_base_info_unref (GIBaseInfo *info)
+{
+ info->ref_count--;
+
+ if (!info->ref_count)
+ {
+ if (info->container)
+ g_base_info_unref (info->container);
+
+ g_free (info);
+ }
+}
+
+GIInfoType
+g_base_info_get_type (GIBaseInfo *info)
+{
+
+ return info->type;
+}
+
+const gchar *
+g_base_info_get_name (GIBaseInfo *info)
+{
+ switch (info->type)
+ {
+ case GI_INFO_TYPE_FUNCTION:
+ case GI_INFO_TYPE_CALLBACK:
+ case GI_INFO_TYPE_STRUCT:
+ case GI_INFO_TYPE_BOXED:
+ case GI_INFO_TYPE_ENUM:
+ case GI_INFO_TYPE_FLAGS:
+ case GI_INFO_TYPE_OBJECT:
+ case GI_INFO_TYPE_INTERFACE:
+ case GI_INFO_TYPE_CONSTANT:
+ case GI_INFO_TYPE_ERROR_DOMAIN:
+ {
+ CommonBlob *blob = (CommonBlob *)&info->metadata[info->offset];
+
+ return g_metadata_get_string (info->metadata, blob->name);
+ }
+ break;
+
+ case GI_INFO_TYPE_VALUE:
+ {
+ ValueBlob *blob = (ValueBlob *)&info->metadata[info->offset];
+
+ return g_metadata_get_string (info->metadata, blob->name);
+ }
+ break;
+
+ case GI_INFO_TYPE_SIGNAL:
+ {
+ SignalBlob *blob = (SignalBlob *)&info->metadata[info->offset];
+
+ return g_metadata_get_string (info->metadata, blob->name);
+ }
+ break;
+
+ case GI_INFO_TYPE_PROPERTY:
+ {
+ PropertyBlob *blob = (PropertyBlob *)&info->metadata[info->offset];
+
+ return g_metadata_get_string (info->metadata, blob->name);
+ }
+ break;
+
+ case GI_INFO_TYPE_VFUNC:
+ {
+ VFuncBlob *blob = (VFuncBlob *)&info->metadata[info->offset];
+
+ return g_metadata_get_string (info->metadata, blob->name);
+ }
+ break;
+
+ case GI_INFO_TYPE_FIELD:
+ {
+ FieldBlob *blob = (FieldBlob *)&info->metadata[info->offset];
+
+ return g_metadata_get_string (info->metadata, blob->name);
+ }
+ break;
+
+ case GI_INFO_TYPE_ARG:
+ {
+ ArgBlob *blob = (ArgBlob *)&info->metadata[info->offset];
+
+ return g_metadata_get_string (info->metadata, blob->name);
+ }
+ break;
+
+ case GI_INFO_TYPE_UNRESOLVED:
+ {
+ GIUnresolvedInfo *unresolved = (GIUnresolvedInfo *)info;
+
+ return unresolved->name;
+ }
+ break;
+
+ case GI_INFO_TYPE_TYPE:
+ default: ;
+ /* unnamed */
+ }
+
+ return NULL;
+}
+
+const gchar *
+g_base_info_get_namespace (GIBaseInfo *info)
+{
+ Header *header = (Header *)info->metadata;
+
+ if (info->type == GI_INFO_TYPE_UNRESOLVED)
+ {
+ GIUnresolvedInfo *unresolved = (GIUnresolvedInfo *)info;
+
+ return unresolved->namespace;
+ }
+
+ return g_metadata_get_string (info->metadata, header->namespace);
+}
+
+gboolean
+g_base_info_is_deprecated (GIBaseInfo *info)
+{
+ switch (info->type)
+ {
+ case GI_INFO_TYPE_FUNCTION:
+ case GI_INFO_TYPE_CALLBACK:
+ case GI_INFO_TYPE_STRUCT:
+ case GI_INFO_TYPE_BOXED:
+ case GI_INFO_TYPE_ENUM:
+ case GI_INFO_TYPE_FLAGS:
+ case GI_INFO_TYPE_OBJECT:
+ case GI_INFO_TYPE_INTERFACE:
+ case GI_INFO_TYPE_CONSTANT:
+ case GI_INFO_TYPE_ERROR_DOMAIN:
+ {
+ CommonBlob *blob = (CommonBlob *)&info->metadata[info->offset];
+
+ return blob->deprecated;
+ }
+ break;
+
+ case GI_INFO_TYPE_VALUE:
+ {
+ ValueBlob *blob = (ValueBlob *)&info->metadata[info->offset];
+
+ return blob->deprecated;
+ }
+ break;
+
+ case GI_INFO_TYPE_SIGNAL:
+ {
+ SignalBlob *blob = (SignalBlob *)&info->metadata[info->offset];
+
+ return blob->deprecated;
+ }
+ break;
+
+ case GI_INFO_TYPE_PROPERTY:
+ {
+ PropertyBlob *blob = (PropertyBlob *)&info->metadata[info->offset];
+
+ return blob->deprecated;
+ }
+ break;
+
+ case GI_INFO_TYPE_VFUNC:
+ case GI_INFO_TYPE_FIELD:
+ case GI_INFO_TYPE_ARG:
+ case GI_INFO_TYPE_TYPE:
+ default: ;
+ /* no deprecation flag for these */
+ }
+
+ return FALSE;
+}
+
+static int
+cmp_annotation (const void *av,
+ const void *bv)
+{
+ const AnnotationBlob *a = av;
+ const AnnotationBlob *b = bv;
+
+ if (b->offset < a->offset)
+ return -1;
+
+ if (b->offset > a->offset)
+ return 1;
+
+ return 0;
+}
+
+const gchar *
+g_base_info_get_annotation (GIBaseInfo *info,
+ const gchar *name)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+ AnnotationBlob blob, *first, *after, *res, *next;
+ const gchar *rname;
+
+ blob.offset = base->offset;
+
+ first = (AnnotationBlob *) &base->metadata[header->annotations];
+ after = (AnnotationBlob *) &base->metadata[header->annotations +
+ header->n_annotations * header->annotation_blob_size];
+
+ res = bsearch (&blob, first, header->n_annotations,
+ header->annotation_blob_size, cmp_annotation);
+
+ if (res == NULL)
+ return NULL;
+
+ next = res;
+ do
+ {
+ res = next;
+ next = res -= header->annotation_blob_size;
+ }
+ while (next >= first && next->offset == base->offset);
+
+ next = res;
+ do
+ {
+ res = next;
+
+ rname = g_metadata_get_string (base->metadata, res->name);
+ if (strcmp (name, rname) == 0)
+ return g_metadata_get_string (base->metadata, res->value);
+
+ next = res += header->annotation_blob_size;
+ }
+ while (next < after && next->offset == base->offset);
+
+ return NULL;
+}
+
+GIBaseInfo *
+g_base_info_get_container (GIBaseInfo *info)
+{
+ info->container;
+}
+
+
+/* GIFunctionInfo functions */
+const gchar *
+g_function_info_get_symbol (GIFunctionInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ FunctionBlob *blob = (FunctionBlob *)&base->metadata[base->offset];
+
+ return g_metadata_get_string (base->metadata, blob->c_name);
+}
+
+GIFunctionInfoFlags
+g_function_info_get_flags (GIFunctionInfo *info)
+{
+ GIFunctionInfoFlags flags;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ FunctionBlob *blob = (FunctionBlob *)&base->metadata[base->offset];
+
+ flags = 0;
+
+ if (base->container != NULL)
+ flags = flags | GI_FUNCTION_IS_METHOD;
+
+ if (blob->constructor)
+ flags = flags | GI_FUNCTION_IS_CONSTRUCTOR;
+
+ if (blob->getter)
+ flags = flags | GI_FUNCTION_IS_GETTER;
+
+ if (blob->setter)
+ flags = flags | GI_FUNCTION_IS_SETTER;
+
+ if (blob->wraps_vfunc)
+ flags = flags | GI_FUNCTION_WRAPS_VFUNC;
+
+ return flags;
+}
+
+GIPropertyInfo *
+g_function_info_get_property (GIFunctionInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ FunctionBlob *blob = (FunctionBlob *)&base->metadata[base->offset];
+ GIInterfaceInfo *container = (GIInterfaceInfo *)base->container;
+
+ return g_interface_info_get_property (container, blob->index);
+}
+
+GIVFuncInfo *
+g_function_info_get_vfunc (GIFunctionInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ FunctionBlob *blob = (FunctionBlob *)&base->metadata[base->offset];
+ GIInterfaceInfo *container = (GIInterfaceInfo *)base->container;
+
+ return g_interface_info_get_vfunc (container, blob->index);
+}
+
+
+/* GICallableInfo functions */
+static guint32
+signature_offset (GICallableInfo *info)
+{
+ switch (info->base.type)
+ {
+ case GI_INFO_TYPE_FUNCTION:
+ case GI_INFO_TYPE_VFUNC:
+ return *(guint32 *)&info->base.metadata[info->base.offset + 12];
+ case GI_INFO_TYPE_CALLBACK:
+ case GI_INFO_TYPE_SIGNAL:
+ return *(guint32 *)&info->base.metadata[info->base.offset + 8];
+ }
+
+ return 0;
+}
+
+GITypeInfo *
+g_type_info_new (GIBaseInfo *container,
+ const guchar *metadata,
+ guint32 offset)
+{
+ Header *header = (Header *)metadata;
+ SimpleTypeBlob *type = (SimpleTypeBlob *)&metadata[offset];
+
+ return (GITypeInfo *) g_info_new (GI_INFO_TYPE_TYPE, container, metadata,
+ type->reserved == 0 ? offset : type->offset);
+}
+
+GITypeInfo *
+g_callable_info_get_return_type (GICallableInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ guint32 offset;
+
+ offset = signature_offset (info);
+
+ return g_type_info_new (base, base->metadata, offset);
+}
+
+Transfer
+g_callable_info_get_caller_owns (GICallableInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ SignatureBlob *blob = (SignatureBlob *)&base->metadata[signature_offset (info)];
+
+ if (blob->caller_owns_return_value)
+ return GI_TRANSFER_EVERYTHING;
+ else if (blob->caller_owns_return_container)
+ return GI_TRANSFER_CONTAINER;
+ else
+ return GI_TRANSFER_NOTHING;
+}
+
+gint
+g_callable_info_get_n_args (GICallableInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ gint offset;
+ SignatureBlob *blob;
+
+ offset = signature_offset (info);
+ blob = (SignatureBlob *)&base->metadata[offset];
+
+ return blob->n_arguments;
+}
+
+GIArgInfo *
+g_callable_info_get_arg (GICallableInfo *info,
+ gint n)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+ gint offset;
+
+ offset = signature_offset (info);
+
+ return (GIArgInfo *) g_info_new (GI_INFO_TYPE_ARG, base, base->metadata,
+ offset + header->signature_blob_size + n * header->arg_blob_size);
+}
+
+/* GIArgInfo function */
+Direction
+g_arg_info_get_direction (GIArgInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ArgBlob *blob = (ArgBlob *)&base->metadata[base->offset];
+
+ if (blob->in && blob->out)
+ return GI_DIRECTION_INOUT;
+ else if (blob->out)
+ return GI_DIRECTION_OUT;
+ else
+ return GI_DIRECTION_IN;
+}
+
+gboolean
+g_arg_info_is_return_value (GIArgInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ArgBlob *blob = (ArgBlob *)&base->metadata[base->offset];
+
+ return blob->return_value;
+}
+
+gboolean
+g_arg_info_is_dipper (GIArgInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ArgBlob *blob = (ArgBlob *)&base->metadata[base->offset];
+
+ return blob->dipper;
+}
+
+gboolean
+g_arg_info_is_optional (GIArgInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ArgBlob *blob = (ArgBlob *)&base->metadata[base->offset];
+
+ return blob->optional;
+}
+
+gboolean
+g_arg_info_may_be_null (GIArgInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ArgBlob *blob = (ArgBlob *)&base->metadata[base->offset];
+
+ return blob->null_ok;
+}
+
+Transfer
+g_arg_info_get_ownership_transfer (GIArgInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ArgBlob *blob = (ArgBlob *)&base->metadata[base->offset];
+
+ if (blob->transfer_ownership)
+ return GI_TRANSFER_EVERYTHING;
+ else if (blob->transfer_container_ownership)
+ return GI_TRANSFER_CONTAINER;
+ else
+ return GI_TRANSFER_NOTHING;
+}
+
+GITypeInfo *
+g_arg_info_get_type (GIArgInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+
+ return g_type_info_new (base, base->metadata, base->offset + 8);
+}
+
+/* GITypeInfo functions */
+gboolean
+g_type_info_is_pointer (GITypeInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ SimpleTypeBlob *type = (SimpleTypeBlob *)&base->metadata[base->offset];
+
+ if (type->reserved == 0)
+ return type->pointer;
+ else
+ {
+ InterfaceTypeBlob *iface = (InterfaceTypeBlob *)&base->metadata[base->offset];
+
+ return iface->pointer;
+ }
+}
+
+GITypeTag
+g_type_info_get_tag (GITypeInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ SimpleTypeBlob *type = (SimpleTypeBlob *)&base->metadata[base->offset];
+
+ if (type->reserved == 0)
+ return type->tag;
+ else
+ {
+ InterfaceTypeBlob *iface = (InterfaceTypeBlob *)&base->metadata[base->offset];
+
+ return iface->tag;
+ }
+}
+
+GITypeInfo *
+g_type_info_get_param_type (GITypeInfo *info,
+ gint n)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ SimpleTypeBlob *type = (SimpleTypeBlob *)&base->metadata[base->offset];
+
+ if (type->reserved != 0)
+ {
+ ParamTypeBlob *param = (ParamTypeBlob *)&base->metadata[base->offset];
+
+ switch (param->tag)
+ {
+ case GI_TYPE_TAG_ARRAY:
+ case GI_TYPE_TAG_GLIST:
+ case GI_TYPE_TAG_GSLIST:
+ case GI_TYPE_TAG_GHASH:
+ return g_type_info_new (base, base->metadata, base->offset + 4 + 4 * n);
+ break;
+
+ default: ;
+ }
+ }
+
+ return NULL;
+}
+
+GIBaseInfo *
+g_type_info_get_interface (GITypeInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ SimpleTypeBlob *type = (SimpleTypeBlob *)&base->metadata[base->offset];
+
+ if (type->reserved != 0)
+ {
+ InterfaceTypeBlob *blob = (InterfaceTypeBlob *)&base->metadata[base->offset];
+
+ if (blob->tag == GI_TYPE_TAG_INTERFACE)
+ return g_info_from_entry (base->metadata, blob->interface);
+ }
+
+ return NULL;
+}
+
+gint
+g_type_info_get_array_length (GITypeInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ SimpleTypeBlob *type = (SimpleTypeBlob *)&base->metadata[base->offset];
+
+ if (type->reserved != 0)
+ {
+ ArrayTypeBlob *blob = (ArrayTypeBlob *)&base->metadata[base->offset];
+
+ if (blob->tag == GI_TYPE_TAG_ARRAY)
+ {
+ if (blob->has_length)
+ return blob->length;
+ }
+ }
+
+ return -1;
+}
+
+gboolean
+g_type_info_is_zero_terminated (GITypeInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ SimpleTypeBlob *type = (SimpleTypeBlob *)&base->metadata[base->offset];
+
+ if (type->reserved != 0)
+ {
+ ArrayTypeBlob *blob = (ArrayTypeBlob *)&base->metadata[base->offset];
+
+ if (blob->tag == GI_TYPE_TAG_ARRAY)
+ return blob->zero_terminated;
+ }
+
+ return FALSE;
+}
+
+gint
+g_type_info_get_n_error_domains (GITypeInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ SimpleTypeBlob *type = (SimpleTypeBlob *)&base->metadata[base->offset];
+
+ if (type->reserved != 0)
+ {
+ ErrorTypeBlob *blob = (ErrorTypeBlob *)&base->metadata[base->offset];
+
+ if (blob->tag == GI_TYPE_TAG_ERROR)
+ return blob->n_domains;
+ }
+
+ return 0;
+}
+
+GIErrorDomainInfo *
+g_type_info_get_error_domain (GITypeInfo *info,
+ gint n)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ SimpleTypeBlob *type = (SimpleTypeBlob *)&base->metadata[base->offset];
+
+ if (type->reserved != 0)
+ {
+ ErrorTypeBlob *blob = (ErrorTypeBlob *)&base->metadata[base->offset];
+
+ if (blob->tag == GI_TYPE_TAG_ERROR)
+ return (GIErrorDomainInfo *) g_info_from_entry (base->metadata,
+ blob->domains[n]);
+ }
+
+ return NULL;
+}
+
+
+/* GIErrorDomainInfo functions */
+const gchar *
+g_error_domain_info_get_quark (GIErrorDomainInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ErrorDomainBlob *blob = (ErrorDomainBlob *)&base->metadata[base->offset];
+
+ return g_metadata_get_string (base->metadata, blob->get_quark);
+}
+
+GIInterfaceInfo *
+g_error_domain_info_get_codes (GIErrorDomainInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ErrorDomainBlob *blob = (ErrorDomainBlob *)&base->metadata[base->offset];
+
+ return (GIInterfaceInfo *) g_info_from_entry (base->metadata, blob->error_codes);
+}
+
+
+
+
+/* GIValueInfo functions */
+const gchar *
+g_value_info_get_short_name (GIValueInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ValueBlob *blob = (ValueBlob *)&base->metadata[base->offset];
+
+ return g_metadata_get_string (base->metadata, blob->short_name);
+}
+
+glong
+g_value_info_get_value (GIValueInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ValueBlob *blob = (ValueBlob *)&base->metadata[base->offset];
+
+ return (glong)blob->value;
+}
+
+/* GIFieldInfo functions */
+GIFieldInfoFlags
+g_field_info_get_flags (GIFieldInfo *info)
+{
+ GIFieldInfoFlags flags;
+
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ FieldBlob *blob = (FieldBlob *)&base->metadata[base->offset];
+
+ flags = 0;
+
+ if (blob->readable)
+ flags = flags | GI_FIELD_IS_READABLE;
+
+ if (blob->writable)
+ flags = flags | GI_FIELD_IS_WRITABLE;
+
+ return flags;
+}
+
+gint
+g_field_info_get_size (GIFieldInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ FieldBlob *blob = (FieldBlob *)&base->metadata[base->offset];
+
+ return blob->bits;
+}
+
+gint
+g_field_info_get_offset (GIFieldInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ FieldBlob *blob = (FieldBlob *)&base->metadata[base->offset];
+
+ return blob->struct_offset;
+}
+
+GITypeInfo *
+g_field_info_get_type (GIFieldInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+
+ return g_type_info_new (base, base->metadata, base->offset + 8);
+}
+
+/* GIRegisteredTypeInfo functions */
+const gchar *
+g_registered_type_info_get_type_name (GIRegisteredTypeInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ RegisteredTypeBlob *blob = (RegisteredTypeBlob *)&base->metadata[base->offset];
+
+ if (blob->gtype_name)
+ return g_metadata_get_string (base->metadata, blob->gtype_name);
+
+ return NULL;
+}
+
+const gchar *
+g_registered_type_info_get_type_init (GIRegisteredTypeInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ RegisteredTypeBlob *blob = (RegisteredTypeBlob *)&base->metadata[base->offset];
+
+ if (blob->gtype_init)
+ return g_metadata_get_string (base->metadata, blob->gtype_init);
+
+ return NULL;
+}
+
+
+/* GIStructInfo functions */
+gint
+g_struct_info_get_n_fields (GIStructInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ StructBlob *blob = (StructBlob *)&base->metadata[base->offset];
+
+ return blob->n_fields;
+}
+
+GIFieldInfo *
+g_struct_info_get_field (GIStructInfo *info,
+ gint n)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+
+ return (GIFieldInfo *) g_info_new (GI_INFO_TYPE_FIELD, base, base->metadata,
+ base->offset + header->struct_blob_size +
+ n * header->field_blob_size);
+}
+
+gint
+g_struct_info_get_n_methods (GIStructInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ StructBlob *blob = (StructBlob *)&base->metadata[base->offset];
+
+ return blob->n_methods;
+}
+
+GIFunctionInfo *
+g_struct_info_get_method (GIStructInfo *info,
+ gint n)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ StructBlob *blob = (StructBlob *)&base->metadata[base->offset];
+ Header *header = (Header *)base->metadata;
+ gint offset;
+
+ offset = base->offset + header->struct_blob_size
+ + blob->n_fields * header->field_blob_size
+ + n * header->function_blob_size;
+ return (GIFunctionInfo *) g_info_new (GI_INFO_TYPE_FUNCTION, base,
+ base->metadata, offset);
+}
+
+static GIFunctionInfo *
+find_method (GIBaseInfo *base,
+ guint32 offset,
+ gint n_methods,
+ const gchar *name)
+{
+ /* FIXME hash */
+ Header *header = (Header *)base->metadata;
+ gint i;
+
+ for (i = 0; i < n_methods; i++)
+ {
+ FunctionBlob *fblob = (FunctionBlob *)&base->metadata[offset];
+ const gchar *fname = (const gchar *)&base->metadata[fblob->name];
+
+ if (strcmp (name, fname) == 0)
+ return (GIFunctionInfo *) g_info_new (GI_INFO_TYPE_FUNCTION, base,
+ base->metadata, offset);
+
+ offset += header->function_blob_size;
+ }
+
+ return NULL;
+}
+
+GIFunctionInfo *
+g_struct_info_find_method (GIStructInfo *info,
+ const gchar *name)
+{
+ gint offset;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+ StructBlob *blob = (StructBlob *)&base->metadata[base->offset];
+
+ offset = base->offset + header->struct_blob_size
+ + blob->n_fields * header->field_blob_size;
+
+ return find_method (base, offset, blob->n_methods, name);
+}
+
+gint
+g_enum_info_get_n_values (GIEnumInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ EnumBlob *blob = (EnumBlob *)&base->metadata[base->offset];
+
+ return blob->n_values;
+}
+
+GIValueInfo *
+g_enum_info_get_value (GIEnumInfo *info,
+ gint n)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+ EnumBlob *blob = (EnumBlob *)&base->metadata[base->offset];
+ gint offset;
+
+ offset = base->offset + header->enum_blob_size
+ + n * header->value_blob_size;
+ return (GIValueInfo *) g_info_new (GI_INFO_TYPE_VALUE, base, base->metadata, offset);
+}
+
+/* GIObjectInfo functions */
+GIObjectInfo *
+g_object_info_get_parent (GIObjectInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ObjectBlob *blob = (ObjectBlob *)&base->metadata[base->offset];
+
+ return (GIObjectInfo *) g_info_from_entry (base->metadata, blob->parent);
+}
+
+gint
+g_object_info_get_n_interfaces (GIObjectInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ObjectBlob *blob = (ObjectBlob *)&base->metadata[base->offset];
+
+ return blob->n_interfaces;
+}
+
+GIInterfaceInfo *
+g_object_info_get_interface (GIObjectInfo *info,
+ gint n)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ObjectBlob *blob = (ObjectBlob *)&base->metadata[base->offset];
+
+ return (GIInterfaceInfo *) g_info_from_entry (base->metadata, blob->interfaces[n]);
+}
+
+gint
+g_object_info_get_n_fields (GIObjectInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ObjectBlob *blob = (ObjectBlob *)&base->metadata[base->offset];
+
+ return blob->n_fields;
+}
+
+GIFieldInfo *
+g_object_info_get_field (GIObjectInfo *info,
+ gint n)
+{
+ gint offset;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+ ObjectBlob *blob = (ObjectBlob *)&base->metadata[base->offset];
+
+ offset = base->offset + header->object_blob_size
+ + (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ + n * header->field_blob_size;
+
+ return (GIFieldInfo *) g_info_new (GI_INFO_TYPE_FIELD, base, base->metadata, offset);
+}
+
+gint
+g_object_info_get_n_properties (GIObjectInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ObjectBlob *blob = (ObjectBlob *)&base->metadata[base->offset];
+
+ return blob->n_properties;
+}
+
+GIPropertyInfo *
+g_object_info_get_property (GIObjectInfo *info,
+ gint n)
+{
+ gint offset;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+ ObjectBlob *blob = (ObjectBlob *)&base->metadata[base->offset];
+
+ offset = base->offset + header->object_blob_size
+ + (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ + blob->n_fields * header->field_blob_size
+ + n * header->property_blob_size;
+
+ return (GIPropertyInfo *) g_info_new (GI_INFO_TYPE_PROPERTY, base,
+ base->metadata, offset);
+}
+
+gint
+g_object_info_get_n_methods (GIObjectInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ObjectBlob *blob = (ObjectBlob *)&base->metadata[base->offset];
+
+ return blob->n_methods;
+}
+
+GIFunctionInfo *
+g_object_info_get_method (GIObjectInfo *info,
+ gint n)
+{
+ gint offset;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+ ObjectBlob *blob = (ObjectBlob *)&base->metadata[base->offset];
+
+ offset = base->offset + header->object_blob_size
+ + (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ + blob->n_fields * header->field_blob_size
+ + blob->n_properties * header->property_blob_size
+ + n * header->function_blob_size;
+
+ return (GIFunctionInfo *) g_info_new (GI_INFO_TYPE_FUNCTION, base,
+ base->metadata, offset);
+}
+
+GIFunctionInfo *
+g_object_info_find_method (GIObjectInfo *info,
+ const gchar *name)
+{
+ gint offset;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+ ObjectBlob *blob = (ObjectBlob *)&base->metadata[base->offset];
+
+ offset = base->offset + header->object_blob_size
+ + (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ + blob->n_fields * header->field_blob_size +
+ + blob->n_properties * header->property_blob_size;
+
+ return find_method (base, offset, blob->n_methods, name);
+}
+
+gint
+g_object_info_get_n_signals (GIObjectInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ObjectBlob *blob = (ObjectBlob *)&base->metadata[base->offset];
+
+ return blob->n_signals;
+}
+
+GISignalInfo *
+g_object_info_get_signal (GIObjectInfo *info,
+ gint n)
+{
+ gint i, offset;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+ ObjectBlob *blob = (ObjectBlob *)&base->metadata[base->offset];
+
+ offset = base->offset + header->object_blob_size
+ + (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ + blob->n_fields * header->field_blob_size
+ + blob->n_properties * header->property_blob_size
+ + blob->n_methods * header->function_blob_size
+ + n * header->signal_blob_size;
+
+ return (GISignalInfo *) g_info_new (GI_INFO_TYPE_SIGNAL, base,
+ base->metadata, offset);
+}
+
+gint
+g_object_info_get_n_vfuncs (GIObjectInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ObjectBlob *blob = (ObjectBlob *)&base->metadata[base->offset];
+
+ return blob->n_vfuncs;
+}
+
+GIVFuncInfo *
+g_object_info_get_vfunc (GIObjectInfo *info,
+ gint n)
+{
+ gint i, offset;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+ ObjectBlob *blob = (ObjectBlob *)&base->metadata[base->offset];
+
+ offset = base->offset + header->object_blob_size
+ + (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ + blob->n_fields * header->field_blob_size
+ + blob->n_properties * header->property_blob_size
+ + blob->n_methods * header->function_blob_size
+ + blob->n_signals * header->signal_blob_size
+ + n * header->vfunc_blob_size;
+
+ return (GIVFuncInfo *) g_info_new (GI_INFO_TYPE_VFUNC, base,
+ base->metadata, offset);
+}
+
+gint
+g_object_info_get_n_constants (GIObjectInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ObjectBlob *blob = (ObjectBlob *)&base->metadata[base->offset];
+
+ return blob->n_constants;
+}
+
+GIConstantInfo *
+g_object_info_get_constant (GIObjectInfo *info,
+ gint n)
+{
+ gint i, offset;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+ ObjectBlob *blob = (ObjectBlob *)&base->metadata[base->offset];
+
+ offset = base->offset + header->object_blob_size
+ + (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ + blob->n_fields * header->field_blob_size
+ + blob->n_properties * header->property_blob_size
+ + blob->n_methods * header->function_blob_size
+ + blob->n_signals * header->signal_blob_size
+ + blob->n_vfuncs * header->vfunc_blob_size
+ + n * header->constant_blob_size;
+
+ return (GIConstantInfo *) g_info_new (GI_INFO_TYPE_CONSTANT, base,
+ base->metadata, offset);
+}
+
+
+/* GIInterfaceInfo functions */
+gint
+g_interface_info_get_n_prerequisites (GIInterfaceInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ InterfaceBlob *blob = (InterfaceBlob *)&base->metadata[base->offset];
+
+ return blob->n_prerequisites;
+}
+
+GIBaseInfo *
+g_interface_info_get_prerequisite (GIInterfaceInfo *info,
+ gint n)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ InterfaceBlob *blob = (InterfaceBlob *)&base->metadata[base->offset];
+
+ return g_info_from_entry (base->metadata, blob->prerequisites[n]);
+}
+
+
+gint
+g_interface_info_get_n_properties (GIInterfaceInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ InterfaceBlob *blob = (InterfaceBlob *)&base->metadata[base->offset];
+
+ return blob->n_properties;
+}
+
+GIPropertyInfo *
+g_interface_info_get_property (GIInterfaceInfo *info,
+ gint n)
+{
+ gint offset;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+ InterfaceBlob *blob = (InterfaceBlob *)&base->metadata[base->offset];
+
+ offset = base->offset + header->interface_blob_size
+ + (blob->n_prerequisites + (blob->n_prerequisites % 2)) * 2
+ + n * header->property_blob_size;
+
+ return (GIPropertyInfo *) g_info_new (GI_INFO_TYPE_PROPERTY, base,
+ base->metadata, offset);
+}
+
+gint
+g_interface_info_get_n_methods (GIInterfaceInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ InterfaceBlob *blob = (InterfaceBlob *)&base->metadata[base->offset];
+
+ return blob->n_methods;
+}
+
+GIFunctionInfo *
+g_interface_info_get_method (GIInterfaceInfo *info,
+ gint n)
+{
+ gint i, offset;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+ InterfaceBlob *blob = (InterfaceBlob *)&base->metadata[base->offset];
+
+ offset = base->offset + header->interface_blob_size
+ + (blob->n_prerequisites + (blob->n_prerequisites % 2)) * 2
+ + blob->n_properties * header->property_blob_size
+ + n * header->function_blob_size;
+
+ return (GIFunctionInfo *) g_info_new (GI_INFO_TYPE_FUNCTION, base,
+ base->metadata, offset);
+}
+
+GIFunctionInfo *
+g_interface_info_find_method (GIInterfaceInfo *info,
+ const gchar *name)
+{
+ gint offset;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+ InterfaceBlob *blob = (InterfaceBlob *)&base->metadata[base->offset];
+
+ offset = base->offset + header->object_blob_size
+ + (blob->n_prerequisites + (blob->n_prerequisites % 2)) * 2
+ + blob->n_properties * header->property_blob_size;
+
+ return find_method (base, offset, blob->n_methods, name);
+}
+
+gint
+g_interface_info_get_n_signals (GIInterfaceInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ InterfaceBlob *blob = (InterfaceBlob *)&base->metadata[base->offset];
+
+ return blob->n_signals;
+}
+
+GISignalInfo *
+g_interface_info_get_signal (GIInterfaceInfo *info,
+ gint n)
+{
+ gint i, offset;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+ InterfaceBlob *blob = (InterfaceBlob *)&base->metadata[base->offset];
+
+ offset = base->offset + header->interface_blob_size
+ + (blob->n_prerequisites + (blob->n_prerequisites % 2)) * 2
+ + blob->n_properties * header->property_blob_size
+ + blob->n_methods * header->function_blob_size
+ + n * header->signal_blob_size;
+
+ return (GISignalInfo *) g_info_new (GI_INFO_TYPE_SIGNAL, base,
+ base->metadata, offset);
+}
+
+gint
+g_interface_info_get_n_vfuncs (GIInterfaceInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ InterfaceBlob *blob = (InterfaceBlob *)&base->metadata[base->offset];
+
+ return blob->n_vfuncs;
+}
+
+GIVFuncInfo *
+g_interface_info_get_vfunc (GIInterfaceInfo *info,
+ gint n)
+{
+ gint i, offset;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+ InterfaceBlob *blob = (InterfaceBlob *)&base->metadata[base->offset];
+
+ offset = base->offset + header->interface_blob_size
+ + (blob->n_prerequisites + (blob->n_prerequisites % 2)) * 2
+ + blob->n_properties * header->property_blob_size
+ + blob->n_methods * header->function_blob_size
+ + blob->n_signals * header->signal_blob_size
+ + n * header->vfunc_blob_size;
+
+ return (GIVFuncInfo *) g_info_new (GI_INFO_TYPE_VFUNC, base,
+ base->metadata, offset);
+}
+
+gint
+g_interface_info_get_n_constants (GIInterfaceInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ InterfaceBlob *blob = (InterfaceBlob *)&base->metadata[base->offset];
+
+ return blob->n_constants;
+}
+
+GIConstantInfo *
+g_interface_info_get_constant (GIInterfaceInfo *info,
+ gint n)
+{
+ gint offset;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->metadata;
+ InterfaceBlob *blob = (InterfaceBlob *)&base->metadata[base->offset];
+
+ offset = base->offset + header->interface_blob_size
+ + (blob->n_prerequisites + (blob->n_prerequisites % 2)) * 2
+ + blob->n_properties * header->property_blob_size
+ + blob->n_methods * header->function_blob_size
+ + blob->n_signals * header->signal_blob_size
+ + blob->n_vfuncs * header->vfunc_blob_size
+ + n * header->constant_blob_size;
+
+ return (GIConstantInfo *) g_info_new (GI_INFO_TYPE_CONSTANT, base,
+ base->metadata, offset);
+}
+
+
+
+
+/* GIPropertyInfo functions */
+GParamFlags
+g_property_info_get_flags (GIPropertyInfo *info)
+{
+ GParamFlags flags;
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ PropertyBlob *blob = (PropertyBlob *)&base->metadata[base->offset];
+
+ flags = 0;
+
+ if (blob->readable)
+ flags = flags | G_PARAM_READABLE;
+
+ if (blob->writable)
+ flags = flags | G_PARAM_WRITABLE;
+
+ if (blob->construct)
+ flags = flags | G_PARAM_CONSTRUCT;
+
+ if (blob->construct_only)
+ flags = flags | G_PARAM_CONSTRUCT_ONLY;
+
+ return flags;
+}
+
+GITypeInfo *
+g_property_info_get_type (GIPropertyInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+
+ return g_type_info_new (base, base->metadata, base->offset + 8);
+}
+
+
+/* GISignalInfo functions */
+GSignalFlags
+g_signal_info_get_flags (GISignalInfo *info)
+{
+ GSignalFlags flags;
+
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ SignalBlob *blob = (SignalBlob *)&base->metadata[base->offset];
+
+ flags = 0;
+
+ if (blob->run_first)
+ flags = flags | G_SIGNAL_RUN_FIRST;
+
+ if (blob->run_last)
+ flags = flags | G_SIGNAL_RUN_LAST;
+
+ if (blob->run_cleanup)
+ flags = flags | G_SIGNAL_RUN_CLEANUP;
+
+ if (blob->no_recurse)
+ flags = flags | G_SIGNAL_NO_RECURSE;
+
+ if (blob->detailed)
+ flags = flags | G_SIGNAL_DETAILED;
+
+ if (blob->action)
+ flags = flags | G_SIGNAL_ACTION;
+
+ if (blob->no_hooks)
+ flags = flags | G_SIGNAL_NO_HOOKS;
+
+ return flags;
+}
+
+GIVFuncInfo *
+g_signal_info_get_class_closure (GISignalInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ SignalBlob *blob = (SignalBlob *)&base->metadata[base->offset];
+
+ if (blob->has_class_closure)
+ return g_interface_info_get_vfunc ((GIInterfaceInfo *)base->container, blob->class_closure);
+
+ return NULL;
+}
+
+gboolean
+g_signal_info_true_stops_emit (GISignalInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ SignalBlob *blob = (SignalBlob *)&base->metadata[base->offset];
+
+ return blob->true_stops_emit;
+}
+
+/* GIVFuncInfo functions */
+GIVFuncInfoFlags
+g_vfunc_info_get_flags (GIVFuncInfo *info)
+{
+ GIVFuncInfoFlags flags;
+
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ VFuncBlob *blob = (VFuncBlob *)&base->metadata[base->offset];
+
+ flags = 0;
+
+ if (blob->must_chain_up)
+ flags = flags | GI_VFUNC_MUST_CHAIN_UP;
+
+ if (blob->must_be_implemented)
+ flags = flags | GI_VFUNC_MUST_OVERRIDE;
+
+ if (blob->must_not_be_implemented)
+ flags = flags | GI_VFUNC_MUST_NOT_OVERRIDE;
+
+ return flags;
+}
+
+gint
+g_vfunc_info_get_offset (GIVFuncInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ VFuncBlob *blob = (VFuncBlob *)&base->metadata[base->offset];
+
+ return blob->struct_offset;
+}
+
+GISignalInfo *
+g_vfunc_info_get_signal (GIVFuncInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ VFuncBlob *blob = (VFuncBlob *)&base->metadata[base->offset];
+
+ if (blob->class_closure)
+ return g_interface_info_get_signal ((GIInterfaceInfo *)base->container, blob->signal);
+
+ return NULL;
+}
+
+
+/* GIConstantInfo functions */
+GITypeInfo *
+g_constant_info_get_type (GIConstantInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+
+ return g_type_info_new (base, base->metadata, base->offset + 8);
+}
+
+gint
+g_constant_info_get_value (GIConstantInfo *info,
+ GArgument *value)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ ConstantBlob *blob = (ConstantBlob *)&base->metadata[base->offset];
+
+ /* FIXME non-basic types ? */
+ if (blob->type.reserved == 0)
+ {
+ if (blob->type.pointer)
+ value->v_pointer = g_memdup (&base->metadata[blob->offset], blob->size);
+ else
+ {
+ switch (blob->type.tag)
+ {
+ case GI_TYPE_TAG_BOOLEAN:
+ value->v_boolean = *(gboolean*)&base->metadata[blob->offset];
+ break;
+ case GI_TYPE_TAG_INT8:
+ value->v_int8 = *(gint8*)&base->metadata[blob->offset];
+ break;
+ case GI_TYPE_TAG_UINT8:
+ value->v_uint8 = *(guint8*)&base->metadata[blob->offset];
+ break;
+ case GI_TYPE_TAG_INT16:
+ value->v_int16 = *(gint16*)&base->metadata[blob->offset];
+ break;
+ case GI_TYPE_TAG_UINT16:
+ value->v_uint16 = *(guint16*)&base->metadata[blob->offset];
+ break;
+ case GI_TYPE_TAG_INT32:
+ value->v_int32 = *(gint32*)&base->metadata[blob->offset];
+ break;
+ case GI_TYPE_TAG_UINT32:
+ value->v_uint32 = *(guint32*)&base->metadata[blob->offset];
+ break;
+ case GI_TYPE_TAG_INT64:
+ value->v_int64 = *(gint64*)&base->metadata[blob->offset];
+ break;
+ case GI_TYPE_TAG_UINT64:
+ value->v_uint64 = *(guint64*)&base->metadata[blob->offset];
+ break;
+ case GI_TYPE_TAG_FLOAT:
+ value->v_float = *(gfloat*)&base->metadata[blob->offset];
+ break;
+ case GI_TYPE_TAG_DOUBLE:
+ value->v_double = *(gdouble*)&base->metadata[blob->offset];
+ break;
+ case GI_TYPE_TAG_INT:
+ value->v_int = *(gint*)&base->metadata[blob->offset];
+ break;
+ case GI_TYPE_TAG_UINT:
+ value->v_uint = *(guint*)&base->metadata[blob->offset];
+ break;
+ case GI_TYPE_TAG_LONG:
+ value->v_long = *(glong*)&base->metadata[blob->offset];
+ break;
+ case GI_TYPE_TAG_ULONG:
+ value->v_ulong = *(gulong*)&base->metadata[blob->offset];
+ break;
+ }
+ }
+ }
+
+ return blob->size;
+}
diff --git a/src/girepository.c b/src/girepository.c
new file mode 100644
index 00000000..482107a7
--- /dev/null
+++ b/src/girepository.c
@@ -0,0 +1,338 @@
+/* GObject introspection: Repository implementation
+ *
+ * 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 <stdio.h>
+
+#include <glib.h>
+#include "girepository.h"
+#include "gmetadata.h"
+
+static GIRepository *default_repository = NULL;
+static GHashTable *default_metadata = NULL;
+
+struct _GIRepositoryPrivate
+{
+ GHashTable *metadata;
+};
+
+G_DEFINE_TYPE (GIRepository, g_irepository, G_TYPE_OBJECT);
+
+static void
+g_irepository_init (GIRepository *repository)
+{
+ repository->priv = G_TYPE_INSTANCE_GET_PRIVATE (repository, G_TYPE_IREPOSITORY,
+ GIRepositoryPrivate);
+}
+
+static void
+g_irepository_finalize (GObject *object)
+{
+ GIRepository *repository = G_IREPOSITORY (object);
+
+ g_hash_table_destroy (repository->priv->metadata);
+
+ (* G_OBJECT_CLASS (g_irepository_parent_class)->finalize) (G_OBJECT (repository));
+}
+
+static void
+g_irepository_class_init (GIRepositoryClass *class)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (class);
+
+ gobject_class->finalize = g_irepository_finalize;
+
+ g_type_class_add_private (class, sizeof (GIRepositoryPrivate));
+}
+
+void
+g_irepository_register (GIRepository *repository,
+ const guchar *metadata)
+{
+ Header *header = (Header *)metadata;
+ const gchar *name;
+ GHashTable *table;
+
+ if (repository != NULL)
+ {
+ if (repository->priv->metadata == NULL)
+ repository->priv->metadata = g_hash_table_new (g_str_hash, g_str_equal);
+ table = repository->priv->metadata;
+ }
+ else
+ {
+ if (default_metadata == NULL)
+ default_metadata = g_hash_table_new (g_str_hash, g_str_equal);
+ table = default_metadata;
+ }
+
+ name = g_metadata_get_string (metadata, header->namespace);
+
+ if (g_hash_table_lookup (table, name))
+ {
+ g_fprintf (stderr, "metadata (%p) for '%s' already registered\n",
+ metadata, name);
+
+ return;
+ }
+
+ g_hash_table_insert (table, (void *)name, (void *)metadata);
+}
+
+void
+g_irepository_unregister (GIRepository *repository,
+ const guchar *metadata)
+{
+ Header *header = (Header *)metadata;
+ const gchar *name;
+ GHashTable *table;
+
+ if (repository != NULL)
+ table = repository->priv->metadata;
+ else
+ table = default_metadata;
+
+ name = g_metadata_get_string (metadata, header->namespace);
+
+ if (!g_hash_table_remove (table, name))
+ {
+ g_fprintf (stderr, "metadata (%p) for '%s' not registered\n",
+ metadata, name);
+ }
+}
+
+GIRepository *
+g_irepository_get_default (void)
+{
+ if (default_repository == NULL)
+ {
+ default_repository = g_object_new (G_TYPE_IREPOSITORY, NULL);
+ if (default_metadata == NULL)
+ default_metadata = g_hash_table_new (g_str_hash, g_str_equal);
+ default_repository->priv->metadata = default_metadata;
+ }
+
+ return default_repository;
+}
+
+static void
+count_interfaces (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ guchar *metadata = (guchar *)value;
+ gint *n_interfaces = (gint *)data;
+
+ *n_interfaces += ((Header *)metadata)->n_local_entries;
+}
+
+gint
+g_irepository_get_n_infos (GIRepository *repository,
+ const gchar *namespace)
+{
+ gint n_interfaces = 0;
+ if (namespace)
+ {
+ guchar *metadata;
+
+ metadata = g_hash_table_lookup (repository->priv->metadata, namespace);
+
+ if (metadata)
+ n_interfaces = ((Header *)metadata)->n_local_entries;
+ }
+ else
+ {
+ g_hash_table_foreach (repository->priv->metadata,
+ count_interfaces, &n_interfaces);
+ }
+
+ return n_interfaces;
+}
+
+typedef struct
+{
+ gint index;
+ const gchar *name;
+ const gchar *type;
+ GIBaseInfo *iface;
+} IfaceData;
+
+static void
+find_interface (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ gint i;
+ guchar *metadata = (guchar *)value;
+ IfaceData *iface_data = (IfaceData *)data;
+ gint index;
+ gint n_entries;
+ guint32 offset;
+ const gchar *name;
+ const gchar *type;
+ DirEntry *entry;
+
+ index = -1;
+ n_entries = ((Header *)metadata)->n_local_entries;
+
+ if (iface_data->name)
+ {
+ for (i = 0; i < n_entries; i++)
+ {
+ entry = g_metadata_get_dir_entry (metadata, i);
+ name = g_metadata_get_string (metadata, entry->name);
+ if (strcmp (name, iface_data->name) == 0)
+ {
+ index = i;
+ break;
+ }
+ }
+ }
+ else if (iface_data->type)
+ {
+ for (i = 0; i < n_entries; i++)
+ {
+ entry = g_metadata_get_dir_entry (metadata, i);
+ if (entry->blob_type < 4)
+ continue;
+
+ offset = *(guint32*)&metadata[entry->offset + 8];
+ type = g_metadata_get_string (metadata, offset);
+ if (strcmp (type, iface_data->type) == 0)
+ {
+ index = i;
+ break;
+ }
+ }
+ }
+ else if (iface_data->index >= n_entries)
+ iface_data->index -= n_entries;
+ else if (iface_data->index >= 0)
+ {
+ index = iface_data->index;
+ iface_data->index = -1;
+ }
+
+ if (index != -1)
+ {
+ entry = g_metadata_get_dir_entry (metadata, index);
+ iface_data->iface = g_info_new (entry->blob_type, NULL,
+ metadata, entry->offset);
+ }
+}
+
+GIBaseInfo *
+g_irepository_get_info (GIRepository *repository,
+ const gchar *namespace,
+ gint index)
+{
+ IfaceData data;
+
+ data.name = NULL;
+ data.type = NULL;
+ data.index = index;
+ data.iface = NULL;
+
+ if (namespace)
+ {
+ guchar *metadata;
+
+ metadata = g_hash_table_lookup (repository->priv->metadata, namespace);
+
+ if (metadata)
+ find_interface ((void *)namespace, metadata, &data);
+ }
+ else
+ g_hash_table_foreach (repository->priv->metadata, find_interface, &data);
+
+ return data.iface;
+}
+
+GIBaseInfo *
+g_irepository_find_by_gtype (GIRepository *repository,
+ GType type)
+{
+ IfaceData data;
+
+ data.name = NULL;
+ data.type = g_type_name (type);
+ data.index = -1;
+ data.iface = NULL;
+
+ g_hash_table_foreach (repository->priv->metadata, find_interface, &data);
+
+ return data.iface;
+}
+
+GIBaseInfo *
+g_irepository_find_by_name (GIRepository *repository,
+ const gchar *namespace,
+ const gchar *name)
+{
+ IfaceData data;
+
+ data.name = name;
+ data.type = NULL;
+ data.index = -1;
+ data.iface = NULL;
+
+ if (namespace)
+ {
+ guchar *metadata;
+
+ metadata = g_hash_table_lookup (repository->priv->metadata, namespace);
+
+ if (metadata)
+ find_interface ((void *)namespace, metadata, &data);
+ }
+ else
+ g_hash_table_foreach (repository->priv->metadata, find_interface, &data);
+
+ return data.iface;
+}
+
+static void
+collect_namespaces (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ GList **list = data;
+
+ *list = g_list_append (*list, key);
+}
+
+gchar **
+g_irepository_get_namespaces (GIRepository *repository)
+{
+ GList *l, *list = NULL;
+ gchar **names;
+ gint i;
+
+ g_hash_table_foreach (repository->priv->metadata, collect_namespaces, &list);
+
+ names = g_malloc0 (sizeof (gchar *) * (g_list_length (list) + 1));
+ i = 0;
+ for (l = list; l; l = l->next)
+ names[i++] = g_strdup (l->data);
+ g_list_free (list);
+
+ return names;
+}
diff --git a/src/girepository.h b/src/girepository.h
new file mode 100644
index 00000000..84cd6192
--- /dev/null
+++ b/src/girepository.h
@@ -0,0 +1,388 @@
+/* GObject introspection: Repository
+ *
+ * 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_IREPOSITORY_H__
+#define __G_IREPOSITORY_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_IREPOSITORY (g_irepository_get_type ())
+#define G_IREPOSITORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_IREPOSITORY, GIRepository))
+
+typedef struct _GIRepository GIRepository;
+typedef struct _GIRepositoryClass GIRepositoryClass;
+typedef struct _GIRepositoryPrivate GIRepositoryPrivate;
+typedef struct _GIBaseInfo GIBaseInfo;
+typedef struct _GICallableInfo GICallableInfo;
+typedef struct _GIFunctionInfo GIFunctionInfo;
+typedef struct _GICallbackInfo GICallbackInfo;
+typedef struct _GIRegisteredTypeInfo GIRegisteredTypeInfo;
+typedef struct _GIStructInfo GIStructInfo;
+typedef struct _GIEnumInfo GIEnumInfo;
+typedef struct _GIObjectInfo GIObjectInfo;
+typedef struct _GIInterfaceInfo GIInterfaceInfo;
+typedef struct _GIConstantInfo GIConstantInfo;
+typedef struct _GIValueInfo GIValueInfo;
+typedef struct _GISignalInfo GISignalInfo;
+typedef struct _GIVFuncInfo GIVFuncInfo;
+typedef struct _GIPropertyInfo GIPropertyInfo;
+typedef struct _GIFieldInfo GIFieldInfo;
+typedef struct _GIArgInfo GIArgInfo;
+typedef struct _GITypeInfo GITypeInfo;
+typedef struct _GIErrorDomainInfo GIErrorDomainInfo;
+typedef struct _GIUnresolvedInfo GIUnresolvedInfo;
+
+
+struct _GIRepository
+{
+ GObject parent;
+
+ /*< private >*/
+ GIRepositoryPrivate *priv;
+};
+
+struct _GIRepositoryClass
+{
+ GObjectClass parent;
+};
+
+
+/* Repository */
+
+GType g_irepository_get_type (void) G_GNUC_CONST;
+GIRepository *g_irepository_get_default (void);
+void g_irepository_register (GIRepository *repository,
+ const guchar *metadata);
+void g_irepository_unregister (GIRepository *repository,
+ const guchar *metadata);
+GIBaseInfo * g_irepository_find_by_name (GIRepository *repository,
+ const gchar *namespace,
+ const gchar *name);
+gchar ** g_irepository_get_namespaces (GIRepository *repository);
+GIBaseInfo * g_irepository_find_by_gtype (GIRepository *repository,
+ GType gtype);
+gint g_irepository_get_n_infos (GIRepository *repository,
+ const gchar *namespace);
+GIBaseInfo * g_irepository_get_info (GIRepository *repository,
+ const gchar *namespace,
+ gint index);
+
+
+/* Types of objects registered in the repository */
+
+typedef enum
+{
+ GI_INFO_TYPE_INVALID,
+ GI_INFO_TYPE_FUNCTION,
+ GI_INFO_TYPE_CALLBACK,
+ GI_INFO_TYPE_STRUCT,
+ GI_INFO_TYPE_BOXED,
+ GI_INFO_TYPE_ENUM,
+ GI_INFO_TYPE_FLAGS,
+ GI_INFO_TYPE_OBJECT,
+ GI_INFO_TYPE_INTERFACE,
+ GI_INFO_TYPE_CONSTANT,
+ GI_INFO_TYPE_ERROR_DOMAIN,
+ GI_INFO_TYPE_VALUE,
+ GI_INFO_TYPE_SIGNAL,
+ GI_INFO_TYPE_VFUNC,
+ GI_INFO_TYPE_PROPERTY,
+ GI_INFO_TYPE_FIELD,
+ GI_INFO_TYPE_ARG,
+ GI_INFO_TYPE_TYPE,
+ GI_INFO_TYPE_UNRESOLVED
+} GIInfoType;
+
+
+/* GIBaseInfo */
+
+GIBaseInfo * g_base_info_ref (GIBaseInfo *info);
+void g_base_info_unref (GIBaseInfo *info);
+GIInfoType g_base_info_get_type (GIBaseInfo *info);
+const gchar * g_base_info_get_name (GIBaseInfo *info);
+const gchar * g_base_info_get_namespace (GIBaseInfo *info);
+gboolean g_base_info_is_deprecated (GIBaseInfo *info);
+const gchar * g_base_info_get_annotation (GIBaseInfo *info,
+ const gchar *name);
+GIBaseInfo * g_base_info_get_container (GIBaseInfo *info);
+
+GIBaseInfo * g_info_new (GIInfoType type,
+ GIBaseInfo *container,
+ const guchar *metadata,
+ guint32 offset);
+
+
+/* GIFunctionInfo */
+
+typedef enum
+{
+ GI_FUNCTION_IS_METHOD = 1 << 0,
+ GI_FUNCTION_IS_CONSTRUCTOR = 1 << 1,
+ GI_FUNCTION_IS_GETTER = 1 << 2,
+ GI_FUNCTION_IS_SETTER = 1 << 3,
+ GI_FUNCTION_WRAPS_VFUNC = 1 << 4
+} GIFunctionInfoFlags;
+
+const gchar * g_function_info_get_symbol (GIFunctionInfo *info);
+GIFunctionInfoFlags g_function_info_get_flags (GIFunctionInfo *info);
+GIPropertyInfo * g_function_info_get_property (GIFunctionInfo *info);
+GIVFuncInfo * g_function_info_get_vfunc (GIFunctionInfo *info);
+
+typedef union
+{
+ gboolean v_boolean;
+ gint8 v_int8;
+ guint8 v_uint8;
+ gint16 v_int16;
+ guint16 v_uint16;
+ gint32 v_int32;
+ guint32 v_uint32;
+ gint64 v_int64;
+ guint64 v_uint64;
+ gfloat v_float;
+ gdouble v_double;
+ gint v_int;
+ guint v_uint;
+ glong v_long;
+ gulong v_ulong;
+ gchar * v_string;
+ gpointer v_pointer;
+} GArgument;
+
+gboolean g_function_info_invoke (GIFunctionInfo *info,
+ const GArgument *in_args,
+ int n_in_args,
+ const GArgument *out_args,
+ int n_out_args,
+ GArgument *return_value);
+
+
+/* GICallableInfo */
+
+typedef enum {
+ GI_TRANSFER_NOTHING,
+ GI_TRANSFER_CONTAINER,
+ GI_TRANSFER_EVERYTHING
+} Transfer;
+
+GITypeInfo * g_callable_info_get_return_type (GICallableInfo *info);
+Transfer g_callable_info_get_caller_owns (GICallableInfo *info);
+gint g_callable_info_get_n_args (GICallableInfo *info);
+GIArgInfo * g_callable_info_get_arg (GICallableInfo *info,
+ gint n);
+
+/* GIArgInfo */
+
+typedef enum {
+ GI_DIRECTION_IN,
+ GI_DIRECTION_OUT,
+ GI_DIRECTION_INOUT
+} Direction;
+
+Direction g_arg_info_get_direction (GIArgInfo *info);
+gboolean g_arg_info_is_dipper (GIArgInfo *info);
+gboolean g_arg_info_is_return_value (GIArgInfo *info);
+gboolean g_arg_info_is_optional (GIArgInfo *info);
+gboolean g_arg_info_may_be_null (GIArgInfo *info);
+Transfer g_arg_info_get_ownership_transfer (GIArgInfo *info);
+GITypeInfo * g_arg_info_get_type (GIArgInfo *info);
+
+
+/* GITypeInfo */
+
+typedef enum {
+ GI_TYPE_TAG_VOID = 0,
+ GI_TYPE_TAG_BOOLEAN = 1,
+ GI_TYPE_TAG_INT8 = 2,
+ GI_TYPE_TAG_UINT8 = 3,
+ GI_TYPE_TAG_INT16 = 4,
+ GI_TYPE_TAG_UINT16 = 5,
+ GI_TYPE_TAG_INT32 = 6,
+ GI_TYPE_TAG_UINT32 = 7,
+ GI_TYPE_TAG_INT64 = 8,
+ GI_TYPE_TAG_UINT64 = 9,
+ GI_TYPE_TAG_FLOAT = 10,
+ GI_TYPE_TAG_DOUBLE = 11,
+ GI_TYPE_TAG_STRING = 12,
+ GI_TYPE_TAG_GSTRING = 13,
+ GI_TYPE_TAG_INT = 14,
+ GI_TYPE_TAG_UINT = 15,
+ GI_TYPE_TAG_LONG = 16,
+ GI_TYPE_TAG_ULONG = 17,
+ GI_TYPE_TAG_ARRAY = 20,
+ GI_TYPE_TAG_INTERFACE = 21,
+ GI_TYPE_TAG_GLIST = 22,
+ GI_TYPE_TAG_GSLIST = 23,
+ GI_TYPE_TAG_GHASH = 24,
+ GI_TYPE_TAG_ERROR = 25
+} GITypeTag;
+
+gboolean g_type_info_is_pointer (GITypeInfo *info);
+GITypeTag g_type_info_get_tag (GITypeInfo *info);
+GITypeInfo * g_type_info_get_param_type (GITypeInfo *info,
+ gint n);
+GIBaseInfo * g_type_info_get_interface (GITypeInfo *info);
+gint g_type_info_get_array_length (GITypeInfo *info);
+gboolean g_type_info_is_zero_terminated (GITypeInfo *info);
+
+gint g_type_info_get_n_error_domains (GITypeInfo *info);
+GIErrorDomainInfo *g_type_info_get_error_domain (GITypeInfo *info,
+ gint n);
+
+/* GIErrorDomainInfo */
+
+const gchar * g_error_domain_info_get_quark (GIErrorDomainInfo *info);
+GIInterfaceInfo * g_error_domain_info_get_codes (GIErrorDomainInfo *info);
+
+
+/* GIValueInfo */
+
+const gchar * g_value_info_get_short_name (GIValueInfo *info);
+glong g_value_info_get_value (GIValueInfo *info);
+
+
+/* GIFieldInfo */
+
+typedef enum
+{
+ GI_FIELD_IS_READABLE = 1 << 0,
+ GI_FIELD_IS_WRITABLE = 1 << 1
+} GIFieldInfoFlags;
+
+GIFieldInfoFlags g_field_info_get_flags (GIFieldInfo *info);
+gint g_field_info_get_size (GIFieldInfo *info);
+gint g_field_info_get_offset (GIFieldInfo *info);
+GITypeInfo * g_field_info_get_type (GIFieldInfo *info);
+
+
+/* GIStructInfo */
+gint g_struct_info_get_n_fields (GIStructInfo *info);
+GIFieldInfo * g_struct_info_get_field (GIStructInfo *info,
+ gint n);
+gint g_struct_info_get_n_methods (GIStructInfo *info);
+GIFunctionInfo * g_struct_info_get_method (GIStructInfo *info,
+ gint n);
+GIFunctionInfo * g_struct_info_find_method (GIStructInfo *info,
+ const gchar *name);
+
+/* GIRegisteredTypeInfo */
+
+const gchar * g_registered_type_info_get_type_name (GIRegisteredTypeInfo *info);
+const gchar * g_registered_type_info_get_type_init (GIRegisteredTypeInfo *info);
+
+
+/* GIEnumInfo */
+
+gint g_enum_info_get_n_values (GIEnumInfo *info);
+GIValueInfo * g_enum_info_get_value (GIEnumInfo *info,
+ gint n);
+
+/* GIObjectInfo */
+
+GIObjectInfo * g_object_info_get_parent (GIObjectInfo *info);
+gint g_object_info_get_n_interfaces (GIObjectInfo *info);
+GIInterfaceInfo * g_object_info_get_interface (GIObjectInfo *info,
+ gint n);
+gint g_object_info_get_n_fields (GIObjectInfo *info);
+GIFieldInfo * g_object_info_get_field (GIObjectInfo *info,
+ gint n);
+gint g_object_info_get_n_properties (GIObjectInfo *info);
+GIPropertyInfo * g_object_info_get_property (GIObjectInfo *info,
+ gint n);
+gint g_object_info_get_n_methods (GIObjectInfo *info);
+GIFunctionInfo * g_object_info_get_method (GIObjectInfo *info,
+ gint n);
+GIFunctionInfo * g_object_info_find_method (GIObjectInfo *info,
+ const gchar *name);
+gint g_object_info_get_n_signals (GIObjectInfo *info);
+GISignalInfo * g_object_info_get_signal (GIObjectInfo *info,
+ gint n);
+gint g_object_info_get_n_vfuncs (GIObjectInfo *info);
+GIVFuncInfo * g_object_info_get_vfunc (GIObjectInfo *info,
+ gint n);
+gint g_object_info_get_n_constants (GIObjectInfo *info);
+GIConstantInfo * g_object_info_get_constant (GIObjectInfo *info,
+ gint n);
+
+
+/* GIInterfaceInfo */
+
+gint g_interface_info_get_n_prerequisites (GIInterfaceInfo *info);
+GIBaseInfo * g_interface_info_get_prerequisite (GIInterfaceInfo *info,
+ gint n);
+gint g_interface_info_get_n_properties (GIInterfaceInfo *info);
+GIPropertyInfo * g_interface_info_get_property (GIInterfaceInfo *info,
+ gint n);
+gint g_interface_info_get_n_methods (GIInterfaceInfo *info);
+GIFunctionInfo * g_interface_info_get_method (GIInterfaceInfo *info,
+ gint n);
+GIFunctionInfo * g_interface_info_find_method (GIInterfaceInfo *info,
+ const gchar *name);
+gint g_interface_info_get_n_signals (GIInterfaceInfo *info);
+GISignalInfo * g_interface_info_get_signal (GIInterfaceInfo *info,
+ gint n);
+gint g_interface_info_get_n_vfuncs (GIInterfaceInfo *info);
+GIVFuncInfo * g_interface_info_get_vfunc (GIInterfaceInfo *info,
+ gint n);
+gint g_interface_info_get_n_constants (GIInterfaceInfo *info);
+GIConstantInfo * g_interface_info_get_constant (GIInterfaceInfo *info,
+ gint n);
+
+
+/* GIPropertyInfo */
+
+GParamFlags g_property_info_get_flags (GIPropertyInfo *info);
+GITypeInfo * g_property_info_get_type (GIPropertyInfo *info);
+
+
+/* GISignalInfo */
+
+GSignalFlags g_signal_info_get_flags (GISignalInfo *info);
+GIVFuncInfo * g_signal_info_get_class_closure (GISignalInfo *info);
+gboolean g_signal_info_true_stops_emit (GISignalInfo *info);
+
+
+/* GIVFuncInfo */
+
+typedef enum
+{
+ GI_VFUNC_MUST_CHAIN_UP = 1 << 0,
+ GI_VFUNC_MUST_OVERRIDE = 1 << 1,
+ GI_VFUNC_MUST_NOT_OVERRIDE = 1 << 2
+} GIVFuncInfoFlags;
+
+GIVFuncInfoFlags g_vfunc_info_get_flags (GIVFuncInfo *info);
+gint g_vfunc_info_get_offset (GIVFuncInfo *info);
+GISignalInfo * g_vfunc_info_get_signal (GIVFuncInfo *info);
+
+
+/* GIConstantInfo */
+
+GITypeInfo * g_constant_info_get_type (GIConstantInfo *info);
+gint g_constant_info_get_value (GIConstantInfo *info,
+ GArgument *value);
+
+
+G_END_DECLS
+
+#endif /* __G_IREPOSITORY_H__ */
+
diff --git a/src/gmetadata.c b/src/gmetadata.c
new file mode 100644
index 00000000..d93a42b1
--- /dev/null
+++ b/src/gmetadata.c
@@ -0,0 +1,65 @@
+/* GObject introspection: 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 <glib.h>
+
+#include "gmetadata.h"
+
+DirEntry *
+g_metadata_get_dir_entry (const guchar *metadata,
+ guint16 index)
+{
+ Header *header = (Header *)metadata;
+
+ return (DirEntry *)&metadata[header->directory + index * header->entry_blob_size];
+}
+
+void
+g_metadata_check_sanity (void)
+{
+ /* Check that struct layout is as we expect */
+ g_assert (sizeof (Header) == 80);
+ 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) == 16);
+ 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);
+}
+
+
diff --git a/src/gmetadata.h b/src/gmetadata.h
new file mode 100644
index 00000000..82cfa638
--- /dev/null
+++ b/src/gmetadata.h
@@ -0,0 +1,462 @@
+/* GObject introspection: struct definitions for 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.
+ */
+
+#ifndef __G_METADATA_H__
+#define __G_METADATA_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
+};
+
+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;
+
+ 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;
+} 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 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 c_name;
+ 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 short_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 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;
+
+
+DirEntry *g_metadata_get_dir_entry (const guchar *metadata,
+ guint16 index);
+
+void g_metadata_check_sanity (void);
+
+#define g_metadata_get_string(metadata,offset) ((const gchar*)&(metadata)[(offset)])
+
+
+G_END_DECLS
+
+#endif /* __G_METADATA_H__ */
+
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644
index 00000000..e26c26a1
--- /dev/null
+++ b/tests/Makefile
@@ -0,0 +1,2 @@
+check:
+ ./roundtrips.sh
diff --git a/tests/array.test b/tests/array.test
new file mode 100644
index 00000000..05ea7625
--- /dev/null
+++ b/tests/array.test
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<api version="1.0">
+ <namespace name="Foo">
+ <function name="Foo.test1" cname="test1">
+ <return-type type="gboolean"/>
+ <parameters>
+ <parameter name="p1" type="gchar*[length=1,zero-terminated=1]" direction="in"/>
+ <parameter name="p2" type="gint" direction="in"/>
+ </parameters>
+ </function>
+ <function name="Foo.test2" cname="test2">
+ <return-type type="gboolean"/>
+ <parameters>
+ <parameter name="p2" type="gint" direction="out"/>
+ <parameter name="p1" type="gchar*[length=0]" direction="out"/>
+ </parameters>
+ </function>
+ <function name="Foo.test3" cname="test3">
+ <return-type type="gboolean"/>
+ <parameters>
+ <parameter name="p1" type="gchar*[zero-terminated=1]" direction="in"/>
+ </parameters>
+ </function>
+ </namespace>
+</api>
diff --git a/tests/boxed.test b/tests/boxed.test
new file mode 100644
index 00000000..70ae1966
--- /dev/null
+++ b/tests/boxed.test
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<api version="1.0">
+ <namespace name="Foo">
+ <boxed name="Foo.boxed1" cname="BoxedType1" get-type="boxed1_get_type" deprecated="1">
+ <field cname="field1" readable="1" writable="1" offset="0" type="guint32" />
+ <method name="Foo.boxed1.frob_boxed1" cname="frob_boxed1">
+ <return-type type="void"/>
+ <parameters>
+ <parameter name="box" type="Foo.boxed1*" direction="in"/>
+ <parameter name="w" type="GList<Foo.boxed2*>" direction="in"/>
+ <parameter name="t" type="GHashTable<gchar*,gint64>" direction="in"/>
+ <parameter name="e" type="GError<>" direction="out"/>
+ </parameters>
+ </method>
+ <method name="Foo.boxed1.lart" cname="lart">
+ <return-type type="gboolean"/>
+ <parameters>
+ <parameter name="box" type="Foo.boxed2*" direction="in"/>
+ <parameter name="val" type="gint*" direction="inout"/>
+ </parameters>
+ </method>
+ </boxed>
+ <function name="Foo.freefunc" cname="freefunc" deprecated="1">
+ <return-type type="gint"/>
+ <parameters>
+ <parameter name="v1" type="gint" direction="in"/>
+ <parameter name="val2" type="gint" direction="in"/>
+ </parameters>
+ </function>
+ <boxed name="Foo.boxed2" cname="BoxedType2" get-type="boxed2_get_type" deprecated="1">
+ </boxed>
+ </namespace>
+</api>
diff --git a/tests/enum.test b/tests/enum.test
new file mode 100644
index 00000000..87e9d638
--- /dev/null
+++ b/tests/enum.test
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<api version="1.0">
+ <namespace name="Foo">
+ <enum name="Foo.Enum1" cname="FooEnum" get-type="foo_enum_get_type">
+ <member name="value1" cname="v1" value="0" />
+ <member name="value2" cname="v1" value="1" />
+ <member name="value3" cname="v1" value="2" />
+ </enum>
+ <flags name="Foo.Flags1" cname="FooFlags" get-type="foo_flags_get_type">
+ <member name="value1" cname="v1" value="1" />
+ <member name="value2" cname="v1" value="2" />
+ <member name="value3" cname="v1" value="4" />
+ </flags>
+ <enum name="Foo.Enum2" cname="FooEnum2">
+ <member name="value1" cname="v1" value="0" />
+ <member name="value2" cname="v1" value="1" />
+ <member name="value3" cname="v1" value="2" />
+ </enum>
+ </namespace>
+</api>
diff --git a/tests/errors.test b/tests/errors.test
new file mode 100644
index 00000000..1e85669a
--- /dev/null
+++ b/tests/errors.test
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<api version="1.0">
+ <namespace name="Foo">
+ <enum name="Foo.ErrorCodes1" cname="ErrorCodes1" get-type="foo_error_codes1_get_type">
+ <member name="Foo.ErrorCodes1.e1" cname="e1" value="0" />
+ <member name="Foo.ErrorCodes1.e2" cname="e2" value="1" deprecated="1" />
+ <member name="Foo.ErrorCodes1.e3" cname="e3" value="2" />
+ </enum>
+ <enum name="Foo.ErrorCodes2" cname="ErrorCodes2" get-type="foo_error_codes2_get_type">
+ <member name="Foo.ErrorCodes2.e1" cname="e1" value="0" />
+ </enum>
+ <errordomain name="Foo.Errors1" get-quark="foo_errors1_get_quark" codes="Foo.ErrorCodes1" />
+ <errordomain name="Foo.Errors2" get-quark="foo_errors2_get_quark" codes="Foo.ErrorCodes2" />
+ <function name="Foo.test1" cname="test1">
+ <return-type type="gboolean"/>
+ <parameters>
+ <parameter name="p1" type="gint" direction="in" null-ok="1"/>
+ <parameter name="p2" type="GError<Foo.Errors1,Foo.Errors2>" direction="out"/>
+ </parameters>
+ </function>
+ </namespace>
+</api>
diff --git a/tests/function.test b/tests/function.test
new file mode 100644
index 00000000..7e632da2
--- /dev/null
+++ b/tests/function.test
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<api version="1.0">
+ <namespace name="Foo">
+ <boxed name="Foo.Boxed1" cname="Boxed1" get-type="boxed1_get_type">
+ </boxed>
+ <function name="Foo.test1" cname="test1" deprecated="1">
+ <return-type type="gboolean"/>
+ <parameters>
+ <parameter name="p1" type="Foo.Boxed1*" direction="in" null-ok="1"/>
+ <parameter name="p2" type="gboolean" direction="out"/>
+ </parameters>
+ </function>
+ <callback name="Foo.callback1" deprecated="1">
+ <return-type type="gboolean"/>
+ <parameters>
+ <parameter name="p1" type="Foo.Boxed1*" direction="in" null-ok="1"/>
+ <parameter name="p2" type="gboolean" direction="out"/>
+ </parameters>
+ </callback>
+ </namespace>
+</api>
diff --git a/tests/gobject.test b/tests/gobject.test
new file mode 100644
index 00000000..47152914
--- /dev/null
+++ b/tests/gobject.test
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<api version="1.0">
+ <namespace name="GObject">
+ <object name="GObject.GObject" cname="GObject" get-type="g_object_get_type">
+ </object>
+ </namespace>
+</api>
diff --git a/tests/interface.test b/tests/interface.test
new file mode 100644
index 00000000..6c9313a6
--- /dev/null
+++ b/tests/interface.test
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<api version="1.0">
+ <namespace name="Foo">
+ <interface name="Foo.Iface1" cname="Iface1" get-type="iface1_get_type">
+ <requires>
+ <interface name="Foo.Iface2" />
+ </requires>
+ <method name="Foo.Iface1.method1" cname="method1">
+ <return-type type="Foo.Iface2*"/>
+ <parameters>
+ <parameter name="param1" type="Foo.Iface2*" direction="in"/>
+ </parameters>
+ </method>
+ <property name="prop1" readable="0" writable="0" type="gint"/>
+ <signal name="signal1" when="LAST">
+ <return-type type="gboolean"/>
+ <parameters>
+ <parameter name="obj" type="Foo.Iface1*" direction="in"/>
+ </parameters>
+ </signal>
+ <signal name="signal2" when="FIRST" no-recurse="1" detailed="1" action="1" no-hooks="1">
+ <return-type type="void"/>
+ <parameters>
+ <parameter name="obj" type="Foo.Iface1*" direction="in"/>
+ </parameters>
+ </signal>
+ <vfunc name="Foo.Iface1.vfunc1">
+ <return-type type="Foo.Iface2*"/>
+ <parameters>
+ <parameter name="param1" type="Foo.Iface2*" direction="in"/>
+ </parameters>
+ </vfunc>
+ <constant name="constant1" type="gint" value="42" />
+ </interface>
+ <interface name="Foo.Iface2" cname="Iface2" get-type="iface2_get_type">
+ </interface>
+ </namespace>
+</api>
diff --git a/tests/object.test b/tests/object.test
new file mode 100644
index 00000000..c4e0cfeb
--- /dev/null
+++ b/tests/object.test
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<api version="1.0">
+ <namespace name="Foo">
+ <object name="Foo.Object1" parent="Foo.Object2" cname="Object1" get-type="object1_get_type">
+ <implements>
+ <interface name="Foo.Iface1" />
+ </implements>
+ <property name="prop1" readable="0" writable="0" type="gint"/>
+ <signal name="signal1" when="LAST">
+ <return-type type="gboolean"/>
+ <parameters>
+ <parameter name="obj" type="Foo.Object1*" direction="in"/>
+ </parameters>
+ </signal>
+ <signal name="signal2" when="FIRST" no-recurse="1" detailed="1" action="1" no-hooks="1">
+ <return-type type="void"/>
+ <parameters>
+ <parameter name="obj" type="Foo.Object1*" direction="in"/>
+ </parameters>
+ </signal>
+ <vfunc name="Foo.Object1.vfunc1">
+ <return-type type="Foo.Object2*"/>
+ <parameters>
+ <parameter name="param1" type="Foo.Object1*" direction="in"/>
+ </parameters>
+ </vfunc>
+ <constant name="constant1" type="gint" value="42" />
+ </object>
+ <interface name="Foo.Iface1" cname="Iface1" get-type="iface1_get_type">
+ </interface>
+ <object name="Foo.Object2" parent="GObject.GObject" cname="Object2" get-type="object2_get_type">
+ </object>
+ </namespace>
+</api>
diff --git a/tests/object.test1 b/tests/object.test1
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tests/object.test1
diff --git a/tests/roundtrips.sh b/tests/roundtrips.sh
new file mode 100755
index 00000000..8ed422af
--- /dev/null
+++ b/tests/roundtrips.sh
@@ -0,0 +1,26 @@
+#! /bin/sh
+
+SIMPLE_TESTS="array.test boxed.test enum.test errors.test function.test interface.test"
+
+for i in $SIMPLE_TESTS; do
+ echo $i
+ ../src/g-idl-compiler --raw $i > $i.1;
+ ../src/g-idl-generate --raw $i.1 > $i.2;
+ diff -u $i $i.2 || exit 1;
+ rm $i.1 $i.2
+done
+
+../src/g-idl-compiler --raw --module=Foo object.test gobject.test > object.test.1
+../src/g-idl-generate --raw object.test.1 > object.test.2
+diff -u object.test object.test.2 || exit 1
+rm object.test.1 object.test.2
+
+../src/g-idl-compiler --raw --module=Foo xref1.test xref2.test > xref1.test.1
+../src/g-idl-generate --raw xref1.test.1 > xref1.test.2
+diff -u xref1.test xref1.test.2 || exit 1
+rm xref1.test.1 xref1.test.2
+
+../src/g-idl-compiler --raw --module=Bar xref1.test xref2.test > xref2.test.1
+../src/g-idl-generate --raw xref2.test.1 > xref2.test.2
+diff -u xref2.test xref2.test.2 || exit 1
+rm xref2.test.1 xref2.test.2
diff --git a/tests/xref1.test b/tests/xref1.test
new file mode 100644
index 00000000..35658028
--- /dev/null
+++ b/tests/xref1.test
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<api version="1.0">
+ <namespace name="Foo">
+ <boxed name="Foo.Boxed" cname="FooBoxed" get-type="foo_boxed_get_type">
+ </boxed>
+ <function name="Foo.test" cname="foo_test">
+ <return-type type="void"/>
+ <parameters>
+ <parameter name="p1" type="Bar.Boxed*" direction="in"/>
+ </parameters>
+ </function>
+ </namespace>
+</api>
diff --git a/tests/xref2.test b/tests/xref2.test
new file mode 100644
index 00000000..78f95c72
--- /dev/null
+++ b/tests/xref2.test
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<api version="1.0">
+ <namespace name="Bar">
+ <boxed name="Bar.Boxed" cname="BarBoxed" get-type="bar_boxed_get_type">
+ </boxed>
+ <function name="Bar.test" cname="bar_test">
+ <return-type type="void"/>
+ <parameters>
+ <parameter name="p1" type="Foo.Boxed*" direction="in"/>
+ </parameters>
+ </function>
+ </namespace>
+</api>