| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- |
| * GObject introspection: IDL generator |
| * |
| * Copyright (C) 2005 Matthias Clasen |
| * Copyright (C) 2008,2009 Red Hat, Inc. |
| * |
| * SPDX-License-Identifier: LGPL-2.1-or-later |
| * |
| * 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 "config.h" |
| |
| #include "girwriter-private.h" |
| |
| #include "gibaseinfo-private.h" |
| #include "girepository.h" |
| #include "girepository-private.h" |
| #include "gitypelib-internal.h" |
| |
| #include <errno.h> |
| #include <string.h> |
| #include <stdio.h> |
| |
| #include <glib.h> |
| #include <glib-object.h> |
| #include <glib/gstdio.h> |
| |
| typedef struct { |
| FILE *file; |
| GSList *stack; |
| gboolean show_all; |
| } Xml; |
| |
| typedef struct { |
| char *name; |
| unsigned has_children : 1; |
| } XmlElement; |
| |
| static XmlElement * |
| xml_element_new (const char *name) |
| { |
| XmlElement *elem; |
| |
| elem = g_slice_new (XmlElement); |
| elem->name = g_strdup (name); |
| elem->has_children = FALSE; |
| return elem; |
| } |
| |
| static void |
| xml_element_free (XmlElement *elem) |
| { |
| g_free (elem->name); |
| g_slice_free (XmlElement, elem); |
| } |
| |
| static void |
| xml_printf (Xml *xml, const char *fmt, ...) G_GNUC_PRINTF (2, 3); |
| |
| static void |
| xml_printf (Xml *xml, const char *fmt, ...) |
| { |
| va_list ap; |
| char *s; |
| |
| va_start (ap, fmt); |
| s = g_markup_vprintf_escaped (fmt, ap); |
| fputs (s, xml->file); |
| g_free (s); |
| va_end (ap); |
| } |
| |
| static void |
| xml_start_element (Xml *xml, const char *element_name) |
| { |
| XmlElement *parent = NULL; |
| |
| if (xml->stack) |
| { |
| parent = xml->stack->data; |
| |
| if (!parent->has_children) |
| xml_printf (xml, ">\n"); |
| |
| parent->has_children = TRUE; |
| } |
| |
| xml_printf (xml, "%*s<%s", g_slist_length(xml->stack)*2, "", element_name); |
| |
| xml->stack = g_slist_prepend (xml->stack, xml_element_new (element_name)); |
| } |
| |
| static void |
| xml_end_element (Xml *xml, const char *name) |
| { |
| XmlElement *elem; |
| |
| g_assert (xml->stack != NULL); |
| |
| elem = xml->stack->data; |
| xml->stack = g_slist_delete_link (xml->stack, xml->stack); |
| |
| if (name != NULL) |
| g_assert_cmpstr (name, ==, elem->name); |
| |
| if (elem->has_children) |
| xml_printf (xml, "%*s</%s>\n", g_slist_length (xml->stack)*2, "", elem->name); |
| else |
| xml_printf (xml, "/>\n"); |
| |
| xml_element_free (elem); |
| } |
| |
| static void |
| xml_end_element_unchecked (Xml *xml) |
| { |
| xml_end_element (xml, NULL); |
| } |
| |
| static Xml * |
| xml_open (FILE *file) |
| { |
| Xml *xml; |
| |
| xml = g_slice_new (Xml); |
| xml->file = file; |
| xml->stack = NULL; |
| |
| return xml; |
| } |
| |
| static void |
| xml_close (Xml *xml) |
| { |
| g_assert (xml->stack == NULL); |
| if (xml->file != NULL) |
| { |
| fflush (xml->file); |
| if (xml->file != stdout) |
| fclose (xml->file); |
| xml->file = NULL; |
| } |
| } |
| |
| static void |
| xml_free (Xml *xml) |
| { |
| xml_close (xml); |
| g_slice_free (Xml, xml); |
| } |
| |
| |
| static void |
| check_unresolved (GIBaseInfo *info) |
| { |
| if (!GI_IS_UNRESOLVED_INFO (info)) |
| return; |
| |
| g_critical ("Found unresolved type '%s' '%s'", |
| gi_base_info_get_name (info), gi_base_info_get_namespace (info)); |
| } |
| |
| static void |
| write_type_name (const char *ns, |
| GIBaseInfo *info, |
| Xml *file) |
| { |
| if (strcmp (ns, gi_base_info_get_namespace (info)) != 0) |
| xml_printf (file, "%s.", gi_base_info_get_namespace (info)); |
| |
| xml_printf (file, "%s", gi_base_info_get_name (info)); |
| } |
| |
| static void |
| write_type_name_attribute (const char *ns, |
| GIBaseInfo *info, |
| const char *attr_name, |
| Xml *file) |
| { |
| xml_printf (file, " %s=\"", attr_name); |
| write_type_name (ns, info, file); |
| xml_printf (file, "\""); |
| } |
| |
| static void |
| write_ownership_transfer (GITransfer transfer, |
| Xml *file) |
| { |
| switch (transfer) |
| { |
| case GI_TRANSFER_NOTHING: |
| xml_printf (file, " transfer-ownership=\"none\""); |
| break; |
| case GI_TRANSFER_CONTAINER: |
| xml_printf (file, " transfer-ownership=\"container\""); |
| break; |
| case GI_TRANSFER_EVERYTHING: |
| xml_printf (file, " transfer-ownership=\"full\""); |
| break; |
| default: |
| g_assert_not_reached (); |
| } |
| } |
| |
| static void |
| write_type_info (const char *ns, |
| GITypeInfo *info, |
| Xml *file) |
| { |
| int tag; |
| GITypeInfo *type; |
| gboolean is_pointer; |
| |
| check_unresolved ((GIBaseInfo*)info); |
| |
| tag = gi_type_info_get_tag (info); |
| is_pointer = gi_type_info_is_pointer (info); |
| |
| if (tag == GI_TYPE_TAG_VOID) |
| { |
| xml_start_element (file, "type"); |
| |
| xml_printf (file, " name=\"%s\"", is_pointer ? "any" : "none"); |
| |
| xml_end_element (file, "type"); |
| } |
| else if (GI_TYPE_TAG_IS_BASIC (tag)) |
| { |
| xml_start_element (file, "type"); |
| xml_printf (file, " name=\"%s\"", gi_type_tag_to_string (tag)); |
| xml_end_element (file, "type"); |
| } |
| else if (tag == GI_TYPE_TAG_ARRAY) |
| { |
| unsigned int length_index; |
| size_t size; |
| const char *name = NULL; |
| |
| xml_start_element (file, "array"); |
| |
| switch (gi_type_info_get_array_type (info)) { |
| case GI_ARRAY_TYPE_C: |
| break; |
| case GI_ARRAY_TYPE_ARRAY: |
| name = "GLib.Array"; |
| break; |
| case GI_ARRAY_TYPE_PTR_ARRAY: |
| name = "GLib.PtrArray"; |
| break; |
| case GI_ARRAY_TYPE_BYTE_ARRAY: |
| name = "GLib.ByteArray"; |
| break; |
| default: |
| break; |
| } |
| |
| if (name) |
| xml_printf (file, " name=\"%s\"", name); |
| |
| type = gi_type_info_get_param_type (info, 0); |
| |
| if (gi_type_info_get_array_length_index (info, &length_index)) |
| xml_printf (file, " length=\"%u\"", length_index); |
| |
| if (gi_type_info_get_array_fixed_size (info, &size)) |
| xml_printf (file, " fixed-size=\"%zu\"", size); |
| |
| if (gi_type_info_is_zero_terminated (info)) |
| xml_printf (file, " zero-terminated=\"1\""); |
| |
| write_type_info (ns, type, file); |
| |
| gi_base_info_unref ((GIBaseInfo *)type); |
| |
| xml_end_element (file, "array"); |
| } |
| else if (tag == GI_TYPE_TAG_INTERFACE) |
| { |
| GIBaseInfo *iface = gi_type_info_get_interface (info); |
| xml_start_element (file, "type"); |
| write_type_name_attribute (ns, iface, "name", file); |
| xml_end_element (file, "type"); |
| gi_base_info_unref (iface); |
| } |
| else if (tag == GI_TYPE_TAG_GLIST) |
| { |
| xml_start_element (file, "type"); |
| xml_printf (file, " name=\"GLib.List\""); |
| type = gi_type_info_get_param_type (info, 0); |
| if (type) |
| { |
| write_type_info (ns, type, file); |
| gi_base_info_unref ((GIBaseInfo *)type); |
| } |
| xml_end_element (file, "type"); |
| } |
| else if (tag == GI_TYPE_TAG_GSLIST) |
| { |
| xml_start_element (file, "type"); |
| xml_printf (file, " name=\"GLib.SList\""); |
| type = gi_type_info_get_param_type (info, 0); |
| if (type) |
| { |
| write_type_info (ns, type, file); |
| gi_base_info_unref ((GIBaseInfo *)type); |
| } |
| xml_end_element (file, "type"); |
| } |
| else if (tag == GI_TYPE_TAG_GHASH) |
| { |
| xml_start_element (file, "type"); |
| xml_printf (file, " name=\"GLib.HashTable\""); |
| type = gi_type_info_get_param_type (info, 0); |
| if (type) |
| { |
| write_type_info (ns, type, file); |
| gi_base_info_unref ((GIBaseInfo *)type); |
| type = gi_type_info_get_param_type (info, 1); |
| write_type_info (ns, type, file); |
| gi_base_info_unref ((GIBaseInfo *)type); |
| } |
| xml_end_element (file, "type"); |
| } |
| else if (tag == GI_TYPE_TAG_ERROR) |
| { |
| xml_start_element (file, "type"); |
| xml_printf (file, " name=\"GLib.Error\""); |
| xml_end_element (file, "type"); |
| } |
| else |
| { |
| g_printerr ("Unhandled type tag %d\n", tag); |
| g_assert_not_reached (); |
| } |
| } |
| |
| static void |
| write_attributes (Xml *file, |
| GIBaseInfo *info) |
| { |
| GIAttributeIter iter = GI_ATTRIBUTE_ITER_INIT; |
| const char *name, *value; |
| |
| while (gi_base_info_iterate_attributes (info, &iter, &name, &value)) |
| { |
| xml_start_element (file, "attribute"); |
| xml_printf (file, " name=\"%s\" value=\"%s\"", name, value); |
| xml_end_element (file, "attribute"); |
| } |
| } |
| |
| static void |
| write_return_value_attributes (Xml *file, |
| GICallableInfo *info) |
| { |
| GIAttributeIter iter = GI_ATTRIBUTE_ITER_INIT; |
| const char *name, *value; |
| |
| while (gi_callable_info_iterate_return_attributes (info, &iter, &name, &value)) |
| { |
| xml_start_element (file, "attribute"); |
| xml_printf (file, " name=\"%s\" value=\"%s\"", name, value); |
| xml_end_element (file, "attribute"); |
| } |
| } |
| |
| static void |
| write_constant_value (const char *ns, |
| GITypeInfo *info, |
| GIArgument *argument, |
| Xml *file); |
| |
| static void |
| write_callback_info (const char *ns, |
| GICallbackInfo *info, |
| Xml *file); |
| |
| static void |
| write_field_info (const char *ns, |
| GIFieldInfo *info, |
| GIConstantInfo *branch, |
| Xml *file) |
| { |
| const char *name; |
| GIFieldInfoFlags flags; |
| size_t size; |
| size_t offset; |
| GITypeInfo *type; |
| GIBaseInfo *interface; |
| GIArgument value; |
| |
| name = gi_base_info_get_name ((GIBaseInfo *)info); |
| flags = gi_field_info_get_flags (info); |
| size = gi_field_info_get_size (info); |
| offset = gi_field_info_get_offset (info); |
| |
| xml_start_element (file, "field"); |
| xml_printf (file, " name=\"%s\"", name); |
| |
| /* Fields are assumed to be read-only |
| * (see also girwriter.py and girparser.c) |
| */ |
| if (!(flags & GI_FIELD_IS_READABLE)) |
| xml_printf (file, " readable=\"0\""); |
| if (flags & GI_FIELD_IS_WRITABLE) |
| xml_printf (file, " writable=\"1\""); |
| |
| if (size) |
| xml_printf (file, " bits=\"%zu\"", size); |
| |
| write_attributes (file, (GIBaseInfo*) info); |
| |
| type = gi_field_info_get_type_info (info); |
| |
| if (branch) |
| { |
| xml_printf (file, " branch=\""); |
| gi_base_info_unref ((GIBaseInfo *)type); |
| type = gi_constant_info_get_type_info (branch); |
| gi_constant_info_get_value (branch, &value); |
| write_constant_value (ns, type, &value, file); |
| xml_printf (file, "\""); |
| } |
| |
| if (file->show_all) |
| { |
| xml_printf (file, "offset=\"%zu\"", offset); |
| } |
| |
| interface = gi_type_info_get_interface (type); |
| if (interface != NULL && GI_IS_CALLBACK_INFO (interface)) |
| write_callback_info (ns, (GICallbackInfo *)interface, file); |
| else |
| write_type_info (ns, type, file); |
| |
| if (interface) |
| gi_base_info_unref (interface); |
| |
| gi_base_info_unref ((GIBaseInfo *)type); |
| |
| xml_end_element (file, "field"); |
| } |
| |
| static void |
| write_callable_info (const char *ns, |
| GICallableInfo *info, |
| Xml *file) |
| { |
| GITypeInfo *type; |
| |
| if (gi_callable_info_can_throw_gerror (info)) |
| xml_printf (file, " throws=\"1\""); |
| |
| write_attributes (file, (GIBaseInfo*) info); |
| |
| type = gi_callable_info_get_return_type (info); |
| |
| xml_start_element (file, "return-value"); |
| |
| write_ownership_transfer (gi_callable_info_get_caller_owns (info), file); |
| |
| if (gi_callable_info_may_return_null (info)) |
| xml_printf (file, " allow-none=\"1\""); |
| |
| if (gi_callable_info_skip_return (info)) |
| xml_printf (file, " skip=\"1\""); |
| |
| write_return_value_attributes (file, info); |
| |
| write_type_info (ns, type, file); |
| |
| xml_end_element (file, "return-value"); |
| |
| if (gi_callable_info_get_n_args (info) <= 0) |
| return; |
| |
| xml_start_element (file, "parameters"); |
| for (unsigned int i = 0; i < gi_callable_info_get_n_args (info); i++) |
| { |
| GIArgInfo *arg = gi_callable_info_get_arg (info, i); |
| unsigned int closure_index, destroy_index; |
| |
| xml_start_element (file, "parameter"); |
| xml_printf (file, " name=\"%s\"", |
| gi_base_info_get_name ((GIBaseInfo *) arg)); |
| |
| write_ownership_transfer (gi_arg_info_get_ownership_transfer (arg), file); |
| |
| switch (gi_arg_info_get_direction (arg)) |
| { |
| case GI_DIRECTION_IN: |
| break; |
| case GI_DIRECTION_OUT: |
| xml_printf (file, " direction=\"out\" caller-allocates=\"%s\"", |
| gi_arg_info_is_caller_allocates (arg) ? "1" : "0"); |
| break; |
| case GI_DIRECTION_INOUT: |
| xml_printf (file, " direction=\"inout\""); |
| break; |
| default: |
| g_assert_not_reached (); |
| } |
| |
| if (gi_arg_info_may_be_null (arg)) |
| xml_printf (file, " allow-none=\"1\""); |
| |
| if (gi_arg_info_is_return_value (arg)) |
| xml_printf (file, " retval=\"1\""); |
| |
| if (gi_arg_info_is_optional (arg)) |
| xml_printf (file, " optional=\"1\""); |
| |
| switch (gi_arg_info_get_scope (arg)) |
| { |
| case GI_SCOPE_TYPE_INVALID: |
| break; |
| case GI_SCOPE_TYPE_CALL: |
| xml_printf (file, " scope=\"call\""); |
| break; |
| case GI_SCOPE_TYPE_ASYNC: |
| xml_printf (file, " scope=\"async\""); |
| break; |
| case GI_SCOPE_TYPE_NOTIFIED: |
| xml_printf (file, " scope=\"notified\""); |
| break; |
| case GI_SCOPE_TYPE_FOREVER: |
| xml_printf (file, " scope=\"forever\""); |
| break; |
| default: |
| g_assert_not_reached (); |
| } |
| |
| if (gi_arg_info_get_closure_index (arg, &closure_index)) |
| xml_printf (file, " closure=\"%u\"", closure_index); |
| |
| if (gi_arg_info_get_destroy_index (arg, &destroy_index)) |
| xml_printf (file, " destroy=\"%u\"", destroy_index); |
| |
| if (gi_arg_info_is_skip (arg)) |
| xml_printf (file, " skip=\"1\""); |
| |
| write_attributes (file, (GIBaseInfo*) arg); |
| |
| type = gi_arg_info_get_type_info (arg); |
| write_type_info (ns, type, file); |
| |
| xml_end_element (file, "parameter"); |
| |
| gi_base_info_unref ((GIBaseInfo *)arg); |
| } |
| |
| xml_end_element (file, "parameters"); |
| gi_base_info_unref ((GIBaseInfo *)type); |
| } |
| |
| static void |
| write_function_info (const char *ns, |
| GIFunctionInfo *info, |
| Xml *file) |
| { |
| GIFunctionInfoFlags flags; |
| const char *tag; |
| const char *name; |
| const char *symbol; |
| gboolean deprecated; |
| |
| flags = gi_function_info_get_flags (info); |
| name = gi_base_info_get_name ((GIBaseInfo *)info); |
| symbol = gi_function_info_get_symbol (info); |
| deprecated = gi_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"; |
| |
| xml_start_element (file, tag); |
| xml_printf (file, " name=\"%s\" c:identifier=\"%s\"", |
| name, symbol); |
| |
| if ((flags & GI_FUNCTION_IS_SETTER) || (flags & GI_FUNCTION_IS_GETTER)) |
| { |
| GIPropertyInfo *property = gi_function_info_get_property (info); |
| |
| if (property != NULL) |
| { |
| const char *property_name = gi_base_info_get_name ((GIBaseInfo *)property); |
| |
| if (flags & GI_FUNCTION_IS_SETTER) |
| xml_printf (file, " glib:set-property=\"%s\"", property_name); |
| else if (flags & GI_FUNCTION_IS_GETTER) |
| xml_printf (file, " glib:get-property=\"%s\"", property_name); |
| |
| gi_base_info_unref ((GIBaseInfo *) property); |
| } |
| } |
| |
| if (deprecated) |
| xml_printf (file, " deprecated=\"1\""); |
| |
| write_callable_info (ns, (GICallableInfo*)info, file); |
| xml_end_element (file, tag); |
| } |
| |
| static void |
| write_callback_info (const char *ns, |
| GICallbackInfo *info, |
| Xml *file) |
| { |
| const char *name; |
| gboolean deprecated; |
| |
| name = gi_base_info_get_name ((GIBaseInfo *)info); |
| deprecated = gi_base_info_is_deprecated ((GIBaseInfo *)info); |
| |
| xml_start_element (file, "callback"); |
| xml_printf (file, " name=\"%s\"", name); |
| |
| if (deprecated) |
| xml_printf (file, " deprecated=\"1\""); |
| |
| write_callable_info (ns, (GICallableInfo*)info, file); |
| xml_end_element (file, "callback"); |
| } |
| |
| static void |
| write_struct_info (const char *ns, |
| GIStructInfo *info, |
| Xml *file) |
| { |
| const char *name; |
| const char *type_name; |
| const char *type_init; |
| const char *func; |
| gboolean deprecated; |
| gboolean is_gtype_struct; |
| gboolean foreign; |
| size_t size; |
| unsigned int n_elts; |
| |
| name = gi_base_info_get_name ((GIBaseInfo *)info); |
| deprecated = gi_base_info_is_deprecated ((GIBaseInfo *)info); |
| |
| type_name = gi_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info); |
| type_init = gi_registered_type_info_get_type_init_function_name ((GIRegisteredTypeInfo*)info); |
| |
| if (gi_registered_type_info_is_boxed (GI_REGISTERED_TYPE_INFO (info))) |
| { |
| xml_start_element (file, "glib:boxed"); |
| xml_printf (file, " glib:name=\"%s\"", name); |
| } |
| else |
| { |
| xml_start_element (file, "record"); |
| xml_printf (file, " name=\"%s\"", name); |
| } |
| |
| if (type_name != NULL) |
| xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init); |
| |
| if (deprecated) |
| xml_printf (file, " deprecated=\"1\""); |
| |
| is_gtype_struct = gi_struct_info_is_gtype_struct (info); |
| if (is_gtype_struct) |
| xml_printf (file, " glib:is-gtype-struct=\"1\""); |
| |
| func = gi_struct_info_get_copy_function_name (info); |
| if (func) |
| xml_printf (file, " copy-function=\"%s\"", func); |
| |
| func = gi_struct_info_get_free_function_name (info); |
| if (func) |
| xml_printf (file, " free-function=\"%s\"", func); |
| |
| write_attributes (file, (GIBaseInfo*) info); |
| |
| size = gi_struct_info_get_size (info); |
| if (file->show_all) |
| xml_printf (file, " size=\"%zu\"", size); |
| |
| foreign = gi_struct_info_is_foreign (info); |
| if (foreign) |
| xml_printf (file, " foreign=\"1\""); |
| |
| n_elts = gi_struct_info_get_n_fields (info) + gi_struct_info_get_n_methods (info); |
| if (n_elts > 0) |
| { |
| for (unsigned int i = 0; i < gi_struct_info_get_n_fields (info); i++) |
| { |
| GIFieldInfo *field = gi_struct_info_get_field (info, i); |
| write_field_info (ns, field, NULL, file); |
| gi_base_info_unref ((GIBaseInfo *)field); |
| } |
| |
| for (unsigned int i = 0; i < gi_struct_info_get_n_methods (info); i++) |
| { |
| GIFunctionInfo *function = gi_struct_info_get_method (info, i); |
| write_function_info (ns, function, file); |
| gi_base_info_unref ((GIBaseInfo *)function); |
| } |
| |
| } |
| |
| xml_end_element_unchecked (file); |
| } |
| |
| static void |
| write_value_info (const char *ns, |
| GIValueInfo *info, |
| Xml *file) |
| { |
| const char *name; |
| int64_t value; |
| char *value_str; |
| gboolean deprecated; |
| |
| name = gi_base_info_get_name ((GIBaseInfo *)info); |
| value = gi_value_info_get_value (info); |
| deprecated = gi_base_info_is_deprecated ((GIBaseInfo *)info); |
| |
| xml_start_element (file, "member"); |
| value_str = g_strdup_printf ("%" G_GINT64_FORMAT, value); |
| xml_printf (file, " name=\"%s\" value=\"%s\"", name, value_str); |
| g_free (value_str); |
| |
| if (deprecated) |
| xml_printf (file, " deprecated=\"1\""); |
| |
| write_attributes (file, (GIBaseInfo*) info); |
| |
| xml_end_element (file, "member"); |
| } |
| |
| static void |
| write_constant_value (const char *ns, |
| GITypeInfo *type, |
| GIArgument *value, |
| Xml *file) |
| { |
| switch (gi_type_info_get_tag (type)) |
| { |
| case GI_TYPE_TAG_BOOLEAN: |
| xml_printf (file, "%d", value->v_boolean); |
| break; |
| case GI_TYPE_TAG_INT8: |
| xml_printf (file, "%d", value->v_int8); |
| break; |
| case GI_TYPE_TAG_UINT8: |
| xml_printf (file, "%d", value->v_uint8); |
| break; |
| case GI_TYPE_TAG_INT16: |
| xml_printf (file, "%" G_GINT16_FORMAT, value->v_int16); |
| break; |
| case GI_TYPE_TAG_UINT16: |
| xml_printf (file, "%" G_GUINT16_FORMAT, value->v_uint16); |
| break; |
| case GI_TYPE_TAG_INT32: |
| xml_printf (file, "%" G_GINT32_FORMAT, value->v_int32); |
| break; |
| case GI_TYPE_TAG_UINT32: |
| xml_printf (file, "%" G_GUINT32_FORMAT, value->v_uint32); |
| break; |
| case GI_TYPE_TAG_INT64: |
| xml_printf (file, "%" G_GINT64_FORMAT, value->v_int64); |
| break; |
| case GI_TYPE_TAG_UINT64: |
| xml_printf (file, "%" G_GUINT64_FORMAT, value->v_uint64); |
| break; |
| case GI_TYPE_TAG_FLOAT: |
| xml_printf (file, "%f", (double)value->v_float); |
| break; |
| case GI_TYPE_TAG_DOUBLE: |
| xml_printf (file, "%f", value->v_double); |
| break; |
| case GI_TYPE_TAG_UTF8: |
| case GI_TYPE_TAG_FILENAME: |
| xml_printf (file, "%s", value->v_string); |
| break; |
| default: |
| g_assert_not_reached (); |
| } |
| } |
| |
| static void |
| write_constant_info (const char *ns, |
| GIConstantInfo *info, |
| Xml *file) |
| { |
| GITypeInfo *type; |
| const char *name; |
| GIArgument value; |
| |
| name = gi_base_info_get_name ((GIBaseInfo *)info); |
| |
| xml_start_element (file, "constant"); |
| xml_printf (file, " name=\"%s\"", name); |
| |
| type = gi_constant_info_get_type_info (info); |
| xml_printf (file, " value=\""); |
| |
| gi_constant_info_get_value (info, &value); |
| write_constant_value (ns, type, &value, file); |
| xml_printf (file, "\""); |
| |
| write_type_info (ns, type, file); |
| |
| write_attributes (file, (GIBaseInfo*) info); |
| |
| xml_end_element (file, "constant"); |
| |
| gi_base_info_unref ((GIBaseInfo *)type); |
| } |
| |
| |
| static void |
| write_enum_info (const char *ns, |
| GIEnumInfo *info, |
| Xml *file) |
| { |
| const char *name; |
| const char *type_name; |
| const char *type_init; |
| const char *error_domain; |
| gboolean deprecated; |
| |
| name = gi_base_info_get_name ((GIBaseInfo *)info); |
| deprecated = gi_base_info_is_deprecated ((GIBaseInfo *)info); |
| |
| type_name = gi_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info); |
| type_init = gi_registered_type_info_get_type_init_function_name ((GIRegisteredTypeInfo*)info); |
| error_domain = gi_enum_info_get_error_domain (info); |
| |
| if (GI_IS_ENUM_INFO (info)) |
| xml_start_element (file, "enumeration"); |
| else |
| xml_start_element (file, "bitfield"); |
| xml_printf (file, " name=\"%s\"", name); |
| |
| if (type_init) |
| xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init); |
| if (error_domain) |
| xml_printf (file, " glib:error-domain=\"%s\"", error_domain); |
| |
| if (deprecated) |
| xml_printf (file, " deprecated=\"1\""); |
| |
| write_attributes (file, (GIBaseInfo*) info); |
| |
| for (unsigned int i = 0; i < gi_enum_info_get_n_values (info); i++) |
| { |
| GIValueInfo *value = gi_enum_info_get_value (info, i); |
| write_value_info (ns, value, file); |
| gi_base_info_unref ((GIBaseInfo *)value); |
| } |
| |
| xml_end_element_unchecked (file); |
| } |
| |
| static void |
| write_signal_info (const char *ns, |
| GISignalInfo *info, |
| Xml *file) |
| { |
| GSignalFlags flags; |
| const char *name; |
| gboolean deprecated; |
| |
| name = gi_base_info_get_name ((GIBaseInfo *)info); |
| flags = gi_signal_info_get_flags (info); |
| deprecated = gi_base_info_is_deprecated ((GIBaseInfo *)info); |
| |
| xml_start_element (file, "glib:signal"); |
| xml_printf (file, " name=\"%s\"", name); |
| |
| if (deprecated) |
| xml_printf (file, " deprecated=\"1\""); |
| |
| if (flags & G_SIGNAL_RUN_FIRST) |
| xml_printf (file, " when=\"FIRST\""); |
| else if (flags & G_SIGNAL_RUN_LAST) |
| xml_printf (file, " when=\"LAST\""); |
| else if (flags & G_SIGNAL_RUN_CLEANUP) |
| xml_printf (file, " when=\"CLEANUP\""); |
| |
| if (flags & G_SIGNAL_NO_RECURSE) |
| xml_printf (file, " no-recurse=\"1\""); |
| |
| if (flags & G_SIGNAL_DETAILED) |
| xml_printf (file, " detailed=\"1\""); |
| |
| if (flags & G_SIGNAL_ACTION) |
| xml_printf (file, " action=\"1\""); |
| |
| if (flags & G_SIGNAL_NO_HOOKS) |
| xml_printf (file, " no-hooks=\"1\""); |
| |
| write_callable_info (ns, (GICallableInfo*)info, file); |
| |
| xml_end_element (file, "glib:signal"); |
| } |
| |
| static void |
| write_vfunc_info (const char *ns, |
| GIVFuncInfo *info, |
| Xml *file) |
| { |
| GIVFuncInfoFlags flags; |
| const char *name; |
| GIFunctionInfo *invoker; |
| gboolean deprecated; |
| size_t offset; |
| |
| name = gi_base_info_get_name ((GIBaseInfo *)info); |
| flags = gi_vfunc_info_get_flags (info); |
| deprecated = gi_base_info_is_deprecated ((GIBaseInfo *)info); |
| offset = gi_vfunc_info_get_offset (info); |
| invoker = gi_vfunc_info_get_invoker (info); |
| |
| xml_start_element (file, "virtual-method"); |
| xml_printf (file, " name=\"%s\"", name); |
| |
| if (deprecated) |
| xml_printf (file, " deprecated=\"1\""); |
| |
| if (flags & GI_VFUNC_MUST_CHAIN_UP) |
| xml_printf (file, " must-chain-up=\"1\""); |
| |
| if (flags & GI_VFUNC_MUST_OVERRIDE) |
| xml_printf (file, " override=\"always\""); |
| else if (flags & GI_VFUNC_MUST_NOT_OVERRIDE) |
| xml_printf (file, " override=\"never\""); |
| |
| xml_printf (file, " offset=\"%zu\"", offset); |
| |
| if (invoker) |
| { |
| xml_printf (file, " invoker=\"%s\"", gi_base_info_get_name ((GIBaseInfo*)invoker)); |
| gi_base_info_unref ((GIBaseInfo *)invoker); |
| } |
| |
| write_callable_info (ns, (GICallableInfo*)info, file); |
| |
| xml_end_element (file, "virtual-method"); |
| } |
| |
| static void |
| write_property_info (const char *ns, |
| GIPropertyInfo *info, |
| Xml *file) |
| { |
| GParamFlags flags; |
| const char *name; |
| gboolean deprecated; |
| GITypeInfo *type; |
| |
| name = gi_base_info_get_name ((GIBaseInfo *)info); |
| flags = gi_property_info_get_flags (info); |
| deprecated = gi_base_info_is_deprecated ((GIBaseInfo *)info); |
| |
| xml_start_element (file, "property"); |
| xml_printf (file, " name=\"%s\"", name); |
| |
| if (deprecated) |
| xml_printf (file, " deprecated=\"1\""); |
| |
| /* Properties are assumed to be read-only (see also girwriter.py) */ |
| if (!(flags & G_PARAM_READABLE)) |
| xml_printf (file, " readable=\"0\""); |
| if (flags & G_PARAM_WRITABLE) |
| xml_printf (file, " writable=\"1\""); |
| |
| if (flags & G_PARAM_CONSTRUCT) |
| xml_printf (file, " construct=\"1\""); |
| |
| if (flags & G_PARAM_CONSTRUCT_ONLY) |
| xml_printf (file, " construct-only=\"1\""); |
| |
| if (flags & G_PARAM_READABLE) |
| { |
| GIFunctionInfo *getter = gi_property_info_get_getter (info); |
| |
| if (getter != NULL) |
| { |
| xml_printf (file, " getter=\"%s\"", gi_base_info_get_name ((GIBaseInfo *) getter)); |
| gi_base_info_unref ((GIBaseInfo *) getter); |
| } |
| } |
| |
| if (flags & G_PARAM_WRITABLE) |
| { |
| GIFunctionInfo *setter = gi_property_info_get_setter (info); |
| |
| if (setter != NULL) |
| { |
| xml_printf (file, " setter=\"%s\"", gi_base_info_get_name ((GIBaseInfo *) setter)); |
| gi_base_info_unref ((GIBaseInfo *) setter); |
| } |
| } |
| |
| write_ownership_transfer (gi_property_info_get_ownership_transfer (info), file); |
| |
| write_attributes (file, (GIBaseInfo*) info); |
| |
| type = gi_property_info_get_type_info (info); |
| |
| write_type_info (ns, type, file); |
| |
| xml_end_element (file, "property"); |
| } |
| |
| static void |
| write_object_info (const char *ns, |
| GIObjectInfo *info, |
| Xml *file) |
| { |
| const char *name; |
| const char *type_name; |
| const char *type_init; |
| const char *func; |
| gboolean deprecated; |
| gboolean is_abstract; |
| gboolean is_fundamental; |
| gboolean is_final; |
| GIObjectInfo *pnode; |
| GIStructInfo *class_struct; |
| |
| name = gi_base_info_get_name ((GIBaseInfo *)info); |
| deprecated = gi_base_info_is_deprecated ((GIBaseInfo *)info); |
| is_abstract = gi_object_info_get_abstract (info); |
| is_fundamental = gi_object_info_get_fundamental (info); |
| is_final = gi_object_info_get_final (info); |
| |
| type_name = gi_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info); |
| type_init = gi_registered_type_info_get_type_init_function_name ((GIRegisteredTypeInfo*)info); |
| xml_start_element (file, "class"); |
| xml_printf (file, " name=\"%s\"", name); |
| |
| pnode = gi_object_info_get_parent (info); |
| if (pnode) |
| { |
| write_type_name_attribute (ns, (GIBaseInfo *)pnode, "parent", file); |
| gi_base_info_unref ((GIBaseInfo *)pnode); |
| } |
| |
| class_struct = gi_object_info_get_class_struct (info); |
| if (class_struct) |
| { |
| write_type_name_attribute (ns, (GIBaseInfo*) class_struct, "glib:type-struct", file); |
| gi_base_info_unref ((GIBaseInfo*)class_struct); |
| } |
| |
| if (is_abstract) |
| xml_printf (file, " abstract=\"1\""); |
| |
| if (is_final) |
| xml_printf (file, " final=\"1\""); |
| |
| xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init); |
| |
| if (is_fundamental) |
| xml_printf (file, " glib:fundamental=\"1\""); |
| |
| func = gi_object_info_get_unref_function_name (info); |
| if (func) |
| xml_printf (file, " glib:unref-function=\"%s\"", func); |
| |
| func = gi_object_info_get_ref_function_name (info); |
| if (func) |
| xml_printf (file, " glib:ref-function=\"%s\"", func); |
| |
| func = gi_object_info_get_set_value_function_name (info); |
| if (func) |
| xml_printf (file, " glib:set-value-function=\"%s\"", func); |
| |
| func = gi_object_info_get_get_value_function_name (info); |
| if (func) |
| xml_printf (file, " glib:get-value-function=\"%s\"", func); |
| |
| if (deprecated) |
| xml_printf (file, " deprecated=\"1\""); |
| |
| write_attributes (file, (GIBaseInfo*) info); |
| |
| if (gi_object_info_get_n_interfaces (info) > 0) |
| { |
| for (unsigned int i = 0; i < gi_object_info_get_n_interfaces (info); i++) |
| { |
| GIInterfaceInfo *imp = gi_object_info_get_interface (info, i); |
| xml_start_element (file, "implements"); |
| write_type_name_attribute (ns, (GIBaseInfo *)imp, "name", file); |
| xml_end_element (file, "implements"); |
| gi_base_info_unref ((GIBaseInfo*)imp); |
| } |
| } |
| |
| for (unsigned int i = 0; i < gi_object_info_get_n_fields (info); i++) |
| { |
| GIFieldInfo *field = gi_object_info_get_field (info, i); |
| write_field_info (ns, field, NULL, file); |
| gi_base_info_unref ((GIBaseInfo *)field); |
| } |
| |
| for (unsigned int i = 0; i < gi_object_info_get_n_methods (info); i++) |
| { |
| GIFunctionInfo *function = gi_object_info_get_method (info, i); |
| write_function_info (ns, function, file); |
| gi_base_info_unref ((GIBaseInfo *)function); |
| } |
| |
| for (unsigned int i = 0; i < gi_object_info_get_n_properties (info); i++) |
| { |
| GIPropertyInfo *prop = gi_object_info_get_property (info, i); |
| write_property_info (ns, prop, file); |
| gi_base_info_unref ((GIBaseInfo *)prop); |
| } |
| |
| for (unsigned int i = 0; i < gi_object_info_get_n_signals (info); i++) |
| { |
| GISignalInfo *signal = gi_object_info_get_signal (info, i); |
| write_signal_info (ns, signal, file); |
| gi_base_info_unref ((GIBaseInfo *)signal); |
| } |
| |
| for (unsigned int i = 0; i < gi_object_info_get_n_vfuncs (info); i++) |
| { |
| GIVFuncInfo *vfunc = gi_object_info_get_vfunc (info, i); |
| write_vfunc_info (ns, vfunc, file); |
| gi_base_info_unref ((GIBaseInfo *)vfunc); |
| } |
| |
| for (unsigned int i = 0; i < gi_object_info_get_n_constants (info); i++) |
| { |
| GIConstantInfo *constant = gi_object_info_get_constant (info, i); |
| write_constant_info (ns, constant, file); |
| gi_base_info_unref ((GIBaseInfo *)constant); |
| } |
| |
| xml_end_element (file, "class"); |
| } |
| |
| static void |
| write_interface_info (const char *ns, |
| GIInterfaceInfo *info, |
| Xml *file) |
| { |
| const char *name; |
| const char *type_name; |
| const char *type_init; |
| GIStructInfo *class_struct; |
| gboolean deprecated; |
| |
| name = gi_base_info_get_name ((GIBaseInfo *)info); |
| deprecated = gi_base_info_is_deprecated ((GIBaseInfo *)info); |
| |
| type_name = gi_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info); |
| type_init = gi_registered_type_info_get_type_init_function_name ((GIRegisteredTypeInfo*)info); |
| xml_start_element (file, "interface"); |
| xml_printf (file, " name=\"%s\" glib:type-name=\"%s\" glib:get-type=\"%s\"", |
| name, type_name, type_init); |
| |
| class_struct = gi_interface_info_get_iface_struct (info); |
| if (class_struct) |
| { |
| write_type_name_attribute (ns, (GIBaseInfo*) class_struct, "glib:type-struct", file); |
| gi_base_info_unref ((GIBaseInfo*)class_struct); |
| } |
| |
| if (deprecated) |
| xml_printf (file, " deprecated=\"1\""); |
| |
| write_attributes (file, (GIBaseInfo*) info); |
| |
| if (gi_interface_info_get_n_prerequisites (info) > 0) |
| { |
| for (unsigned int i = 0; i < gi_interface_info_get_n_prerequisites (info); i++) |
| { |
| GIBaseInfo *req = gi_interface_info_get_prerequisite (info, i); |
| |
| xml_start_element (file, "prerequisite"); |
| write_type_name_attribute (ns, req, "name", file); |
| |
| xml_end_element_unchecked (file); |
| gi_base_info_unref (req); |
| } |
| } |
| |
| for (unsigned int i = 0; i < gi_interface_info_get_n_methods (info); i++) |
| { |
| GIFunctionInfo *function = gi_interface_info_get_method (info, i); |
| write_function_info (ns, function, file); |
| gi_base_info_unref ((GIBaseInfo *)function); |
| } |
| |
| for (unsigned int i = 0; i < gi_interface_info_get_n_properties (info); i++) |
| { |
| GIPropertyInfo *prop = gi_interface_info_get_property (info, i); |
| write_property_info (ns, prop, file); |
| gi_base_info_unref ((GIBaseInfo *)prop); |
| } |
| |
| for (unsigned int i = 0; i < gi_interface_info_get_n_signals (info); i++) |
| { |
| GISignalInfo *signal = gi_interface_info_get_signal (info, i); |
| write_signal_info (ns, signal, file); |
| gi_base_info_unref ((GIBaseInfo *)signal); |
| } |
| |
| for (unsigned int i = 0; i < gi_interface_info_get_n_vfuncs (info); i++) |
| { |
| GIVFuncInfo *vfunc = gi_interface_info_get_vfunc (info, i); |
| write_vfunc_info (ns, vfunc, file); |
| gi_base_info_unref ((GIBaseInfo *)vfunc); |
| } |
| |
| for (unsigned int i = 0; i < gi_interface_info_get_n_constants (info); i++) |
| { |
| GIConstantInfo *constant = gi_interface_info_get_constant (info, i); |
| write_constant_info (ns, constant, file); |
| gi_base_info_unref ((GIBaseInfo *)constant); |
| } |
| |
| xml_end_element (file, "interface"); |
| } |
| |
| static void |
| write_union_info (const char *ns, |
| GIUnionInfo *info, |
| Xml *file) |
| { |
| const char *name; |
| const char *type_name; |
| const char *type_init; |
| const char *func; |
| gboolean deprecated; |
| size_t size; |
| |
| name = gi_base_info_get_name ((GIBaseInfo *)info); |
| deprecated = gi_base_info_is_deprecated ((GIBaseInfo *)info); |
| |
| type_name = gi_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info); |
| type_init = gi_registered_type_info_get_type_init_function_name ((GIRegisteredTypeInfo*)info); |
| |
| /* FIXME: Add support for boxed unions */ |
| xml_start_element (file, "union"); |
| xml_printf (file, " name=\"%s\"", name); |
| |
| if (type_name) |
| xml_printf (file, " type-name=\"%s\" get-type=\"%s\"", type_name, type_init); |
| |
| if (deprecated) |
| xml_printf (file, " deprecated=\"1\""); |
| |
| size = gi_union_info_get_size (info); |
| if (file->show_all) |
| xml_printf (file, " size=\"%" G_GSIZE_FORMAT "\"", size); |
| |
| func = gi_union_info_get_copy_function_name (info); |
| if (func) |
| xml_printf (file, " copy-function=\"%s\"", func); |
| |
| func = gi_union_info_get_free_function_name (info); |
| if (func) |
| xml_printf (file, " free-function=\"%s\"", func); |
| |
| write_attributes (file, (GIBaseInfo*) info); |
| |
| if (gi_union_info_is_discriminated (info)) |
| { |
| size_t offset; |
| GITypeInfo *type; |
| |
| gi_union_info_get_discriminator_offset (info, &offset); |
| type = gi_union_info_get_discriminator_type (info); |
| |
| xml_start_element (file, "discriminator"); |
| xml_printf (file, " offset=\"%zu\" type=\"", offset); |
| write_type_info (ns, type, file); |
| xml_end_element (file, "discriminator"); |
| gi_base_info_unref ((GIBaseInfo *)type); |
| } |
| |
| for (unsigned int i = 0; i < gi_union_info_get_n_fields (info); i++) |
| { |
| GIFieldInfo *field = gi_union_info_get_field (info, i); |
| GIConstantInfo *constant = gi_union_info_get_discriminator (info, i); |
| write_field_info (ns, field, constant, file); |
| gi_base_info_unref ((GIBaseInfo *)field); |
| if (constant) |
| gi_base_info_unref ((GIBaseInfo *)constant); |
| } |
| |
| for (unsigned int i = 0; i < gi_union_info_get_n_methods (info); i++) |
| { |
| GIFunctionInfo *function = gi_union_info_get_method (info, i); |
| write_function_info (ns, function, file); |
| gi_base_info_unref ((GIBaseInfo *)function); |
| } |
| |
| xml_end_element (file, "union"); |
| } |
| |
| |
| /** |
| * gi_ir_writer_write: |
| * @repository: repository containing @ns |
| * @filename: (type filename): filename to write to |
| * @ns: GIR namespace to write |
| * @needs_prefix: if the filename needs prefixing |
| * @show_all: if field size calculations should be included |
| * |
| * Writes the output of a typelib represented by @ns |
| * into a GIR xml file named @filename. |
| * |
| * Since: 2.80 |
| */ |
| void |
| gi_ir_writer_write (GIRepository *repository, |
| const char *filename, |
| const char *ns, |
| gboolean needs_prefix, |
| gboolean show_all) |
| { |
| FILE *ofile; |
| size_t i, j; |
| char **dependencies; |
| Xml *xml; |
| |
| if (filename == NULL) |
| ofile = stdout; |
| else |
| { |
| char *full_filename; |
| |
| if (needs_prefix) |
| full_filename = g_strdup_printf ("%s-%s", ns, filename); |
| else |
| full_filename = g_strdup (filename); |
| ofile = g_fopen (filename, "w"); |
| |
| if (ofile == NULL) |
| { |
| g_fprintf (stderr, "failed to open '%s': %s\n", |
| full_filename, g_strerror (errno)); |
| g_free (full_filename); |
| |
| return; |
| } |
| |
| g_free (full_filename); |
| } |
| |
| xml = xml_open (ofile); |
| xml->show_all = show_all; |
| xml_printf (xml, "<?xml version=\"1.0\"?>\n"); |
| xml_start_element (xml, "repository"); |
| xml_printf (xml, " version=\"1.0\"\n" |
| " xmlns=\"http://www.gtk.org/introspection/core/1.0\"\n" |
| " xmlns:c=\"http://www.gtk.org/introspection/c/1.0\"\n" |
| " xmlns:glib=\"http://www.gtk.org/introspection/glib/1.0\""); |
| |
| dependencies = gi_repository_get_immediate_dependencies (repository, ns, NULL); |
| if (dependencies != NULL) |
| { |
| for (i = 0; dependencies[i]; i++) |
| { |
| char **parts = g_strsplit (dependencies[i], "-", 2); |
| xml_start_element (xml, "include"); |
| xml_printf (xml, " name=\"%s\" version=\"%s\"", parts[0], parts[1]); |
| xml_end_element (xml, "include"); |
| g_strfreev (parts); |
| } |
| } |
| |
| if (TRUE) |
| { |
| const char * const *shared_libraries; |
| const char *c_prefix; |
| const char *cur_ns = ns; |
| const char *cur_version; |
| unsigned int n_infos; |
| |
| cur_version = gi_repository_get_version (repository, cur_ns); |
| |
| shared_libraries = gi_repository_get_shared_libraries (repository, cur_ns, NULL); |
| c_prefix = gi_repository_get_c_prefix (repository, cur_ns); |
| xml_start_element (xml, "namespace"); |
| xml_printf (xml, " name=\"%s\" version=\"%s\"", cur_ns, cur_version); |
| if (shared_libraries != NULL) |
| { |
| char *shared_libraries_str = g_strjoinv (",", (char **) shared_libraries); |
| xml_printf (xml, " shared-library=\"%s\"", shared_libraries_str); |
| g_free (shared_libraries_str); |
| } |
| if (c_prefix) |
| xml_printf (xml, " c:prefix=\"%s\"", c_prefix); |
| |
| n_infos = gi_repository_get_n_infos (repository, cur_ns); |
| for (j = 0; j < n_infos; j++) |
| { |
| GIBaseInfo *info = gi_repository_get_info (repository, cur_ns, j); |
| |
| if (GI_IS_FUNCTION_INFO (info)) |
| write_function_info (ns, (GIFunctionInfo *)info, xml); |
| else if (GI_IS_CALLBACK_INFO (info)) |
| write_callback_info (ns, (GICallbackInfo *)info, xml); |
| else if (GI_IS_STRUCT_INFO (info)) |
| write_struct_info (ns, (GIStructInfo *)info, xml); |
| else if (GI_IS_UNION_INFO (info)) |
| write_union_info (ns, (GIUnionInfo *)info, xml); |
| else if (GI_IS_ENUM_INFO (info) || |
| GI_IS_FLAGS_INFO (info)) |
| write_enum_info (ns, (GIEnumInfo *)info, xml); |
| else if (GI_IS_CONSTANT_INFO (info)) |
| write_constant_info (ns, (GIConstantInfo *)info, xml); |
| else if (GI_IS_OBJECT_INFO (info)) |
| write_object_info (ns, (GIObjectInfo *)info, xml); |
| else if (GI_IS_INTERFACE_INFO (info)) |
| write_interface_info (ns, (GIInterfaceInfo *)info, xml); |
| else |
| g_error ("unknown info type %s", g_type_name (G_TYPE_FROM_INSTANCE (info))); |
| |
| gi_base_info_unref (info); |
| } |
| |
| xml_end_element (xml, "namespace"); |
| } |
| |
| xml_end_element (xml, "repository"); |
| |
| xml_free (xml); |
| } |