Imported Upstream version 1.43.92
[platform/upstream/gobject-introspection.git] / girepository / girwriter.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2  * GObject introspection: IDL generator
3  *
4  * Copyright (C) 2005 Matthias Clasen
5  * Copyright (C) 2008,2009 Red Hat, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <errno.h>
24 #include <string.h>
25 #include <stdio.h>
26
27 #include <glib.h>
28 #include <glib-object.h>
29 #include <glib/gstdio.h>
30
31 #include "girwriter.h"
32 #include "girepository.h"
33 #include "gitypelib-internal.h"
34
35 typedef struct {
36   FILE *file;
37   GSList *stack;
38   gboolean show_all;
39 } Xml;
40
41 typedef struct {
42   char *name;
43   guint has_children : 1;
44 } XmlElement;
45
46 static XmlElement *
47 xml_element_new (const char *name)
48 {
49   XmlElement *elem;
50
51   elem = g_slice_new (XmlElement);
52   elem->name = g_strdup (name);
53   elem->has_children = FALSE;
54   return elem;
55 }
56
57 static void
58 xml_element_free (XmlElement *elem)
59 {
60   g_free (elem->name);
61   g_slice_free (XmlElement, elem);
62 }
63
64 static void
65 xml_printf (Xml *xml, const char *fmt, ...)
66 {
67   va_list ap;
68   char *s;
69
70   va_start (ap, fmt);
71   s = g_markup_vprintf_escaped (fmt, ap);
72   fputs (s, xml->file);
73   g_free (s);
74   va_end (ap);
75 }
76
77 static void
78 xml_start_element (Xml *xml, const char *element_name)
79 {
80   XmlElement *parent = NULL;
81
82   if (xml->stack)
83     {
84       parent = xml->stack->data;
85
86       if (!parent->has_children)
87         xml_printf (xml, ">\n");
88
89       parent->has_children = TRUE;
90     }
91
92   xml_printf (xml, "%*s<%s", g_slist_length(xml->stack)*2, "", element_name);
93
94   xml->stack = g_slist_prepend (xml->stack, xml_element_new (element_name));
95 }
96
97 static void
98 xml_end_element (Xml *xml, const char *name)
99 {
100   XmlElement *elem;
101
102   g_assert (xml->stack != NULL);
103
104   elem = xml->stack->data;
105   xml->stack = g_slist_delete_link (xml->stack, xml->stack);
106
107   if (name != NULL)
108     g_assert_cmpstr (name, ==, elem->name);
109
110   if (elem->has_children)
111     xml_printf (xml, "%*s</%s>\n", g_slist_length (xml->stack)*2, "", elem->name);
112   else
113     xml_printf (xml, "/>\n");
114
115   xml_element_free (elem);
116 }
117
118 static void
119 xml_end_element_unchecked (Xml *xml)
120 {
121   xml_end_element (xml, NULL);
122 }
123
124 static Xml *
125 xml_open (FILE *file)
126 {
127   Xml *xml;
128
129   xml = g_slice_new (Xml);
130   xml->file = file;
131   xml->stack = NULL;
132
133   return xml;
134 }
135
136 static void
137 xml_close (Xml *xml)
138 {
139   g_assert (xml->stack == NULL);
140   if (xml->file != NULL)
141     {
142       fflush (xml->file);
143       if (xml->file != stdout)
144         fclose (xml->file);
145       xml->file = NULL;
146     }
147 }
148
149 static void
150 xml_free (Xml *xml)
151 {
152   xml_close (xml);
153   g_slice_free (Xml, xml);
154 }
155
156
157 static void
158 check_unresolved (GIBaseInfo *info)
159 {
160   if (g_base_info_get_type (info) != GI_INFO_TYPE_UNRESOLVED)
161     return;
162
163   g_critical ("Found unresolved type '%s' '%s'\n",
164               g_base_info_get_name (info), g_base_info_get_namespace (info));
165 }
166
167 static void
168 write_type_name (const gchar *namespace,
169                  GIBaseInfo  *info,
170                  Xml         *file)
171 {
172   if (strcmp (namespace, g_base_info_get_namespace (info)) != 0)
173     xml_printf (file, "%s.", g_base_info_get_namespace (info));
174
175   xml_printf (file, "%s", g_base_info_get_name (info));
176 }
177
178 static void
179 write_type_name_attribute (const gchar *namespace,
180                            GIBaseInfo  *info,
181                            const char  *attr_name,
182                            Xml         *file)
183 {
184   xml_printf (file, " %s=\"", attr_name);
185   write_type_name (namespace, info, file);
186   xml_printf (file, "\"");
187 }
188
189  static void
190 write_ownership_transfer (GITransfer transfer,
191                           Xml       *file)
192 {
193   switch (transfer)
194     {
195     case GI_TRANSFER_NOTHING:
196       xml_printf (file, " transfer-ownership=\"none\"");
197       break;
198     case GI_TRANSFER_CONTAINER:
199       xml_printf (file, " transfer-ownership=\"container\"");
200       break;
201     case GI_TRANSFER_EVERYTHING:
202       xml_printf (file, " transfer-ownership=\"full\"");
203       break;
204     default:
205       g_assert_not_reached ();
206     }
207 }
208
209 static void
210 write_type_info (const gchar *namespace,
211                  GITypeInfo  *info,
212                  Xml         *file)
213 {
214   gint tag;
215   GITypeInfo *type;
216   gboolean is_pointer;
217
218   check_unresolved ((GIBaseInfo*)info);
219
220   tag = g_type_info_get_tag (info);
221   is_pointer = g_type_info_is_pointer (info);
222
223   if (tag == GI_TYPE_TAG_VOID)
224     {
225       xml_start_element (file, "type");
226
227       xml_printf (file, " name=\"%s\"", is_pointer ? "any" : "none");
228
229       xml_end_element (file, "type");
230     }
231   else if (G_TYPE_TAG_IS_BASIC (tag))
232     {
233       xml_start_element (file, "type");
234       xml_printf (file, " name=\"%s\"", g_type_tag_to_string (tag));
235       xml_end_element (file, "type");
236     }
237   else if (tag == GI_TYPE_TAG_ARRAY)
238     {
239       gint length, size;
240       char *name = NULL;
241
242       xml_start_element (file, "array");
243
244       switch (g_type_info_get_array_type (info)) {
245         case GI_ARRAY_TYPE_C:
246             break;
247         case GI_ARRAY_TYPE_ARRAY:
248             name = "GLib.Array";
249             break;
250         case GI_ARRAY_TYPE_PTR_ARRAY:
251             name = "GLib.PtrArray";
252             break;
253         case GI_ARRAY_TYPE_BYTE_ARRAY:
254             name = "GLib.ByteArray";
255             break;
256         default:
257             break;
258       }
259
260       if (name)
261         xml_printf (file, " name=\"%s\"", name);
262
263       type = g_type_info_get_param_type (info, 0);
264
265       length = g_type_info_get_array_length (info);
266       if (length >= 0)
267         xml_printf (file, " length=\"%d\"", length);
268
269       size = g_type_info_get_array_fixed_size (info);
270       if (size >= 0)
271         xml_printf (file, " fixed-size=\"%d\"", size);
272
273       if (g_type_info_is_zero_terminated (info))
274         xml_printf (file, " zero-terminated=\"1\"");
275
276       write_type_info (namespace, type, file);
277
278       g_base_info_unref ((GIBaseInfo *)type);
279
280       xml_end_element (file, "array");
281     }
282   else if (tag == GI_TYPE_TAG_INTERFACE)
283     {
284       GIBaseInfo *iface = g_type_info_get_interface (info);
285       xml_start_element (file, "type");
286       write_type_name_attribute (namespace, iface, "name", file);
287       xml_end_element (file, "type");
288       g_base_info_unref (iface);
289     }
290   else if (tag == GI_TYPE_TAG_GLIST)
291     {
292       xml_start_element (file, "type");
293       xml_printf (file, " name=\"GLib.List\"");
294       type = g_type_info_get_param_type (info, 0);
295       if (type)
296         {
297           write_type_info (namespace, type, file);
298           g_base_info_unref ((GIBaseInfo *)type);
299         }
300       xml_end_element (file, "type");
301     }
302   else if (tag == GI_TYPE_TAG_GSLIST)
303     {
304       xml_start_element (file, "type");
305       xml_printf (file, " name=\"GLib.SList\"");
306       type = g_type_info_get_param_type (info, 0);
307       if (type)
308         {
309           write_type_info (namespace, type, file);
310           g_base_info_unref ((GIBaseInfo *)type);
311         }
312       xml_end_element (file, "type");
313     }
314   else if (tag == GI_TYPE_TAG_GHASH)
315     {
316       xml_start_element (file, "type");
317       xml_printf (file, " name=\"GLib.HashTable\"");
318       type = g_type_info_get_param_type (info, 0);
319       if (type)
320         {
321           write_type_info (namespace, type, file);
322           g_base_info_unref ((GIBaseInfo *)type);
323           type = g_type_info_get_param_type (info, 1);
324           write_type_info (namespace, type, file);
325           g_base_info_unref ((GIBaseInfo *)type);
326         }
327       xml_end_element (file, "type");
328     }
329   else if (tag == GI_TYPE_TAG_ERROR)
330     {
331       xml_start_element (file, "type");
332       xml_printf (file, " name=\"GLib.Error\"");
333       xml_end_element (file, "type");
334     }
335   else
336     {
337       g_printerr ("Unhandled type tag %d\n", tag);
338       g_assert_not_reached ();
339     }
340 }
341
342 static void
343 write_attributes (Xml *file,
344                   GIBaseInfo *info)
345 {
346   GIAttributeIter iter = { 0, };
347   char *name, *value;
348
349   while (g_base_info_iterate_attributes (info, &iter, &name, &value))
350     {
351       xml_start_element (file, "attribute");
352       xml_printf (file, " name=\"%s\" value=\"%s\"", name, value);
353       xml_end_element (file, "attribute");
354     }
355 }
356
357 static void
358 write_return_value_attributes (Xml *file,
359                                GICallableInfo *info)
360 {
361   GIAttributeIter iter = { 0, };
362   char *name, *value;
363
364   while (g_callable_info_iterate_return_attributes (info, &iter, &name, &value))
365     {
366       xml_start_element (file, "attribute");
367       xml_printf (file, " name=\"%s\" value=\"%s\"", name, value);
368       xml_end_element (file, "attribute");
369     }
370 }
371
372 static void
373 write_constant_value (const gchar *namespace,
374                       GITypeInfo *info,
375                       GIArgument *argument,
376                       Xml *file);
377
378 static void
379 write_callback_info (const gchar    *namespace,
380                      GICallbackInfo *info,
381                      Xml            *file);
382
383 static void
384 write_field_info (const gchar *namespace,
385                   GIFieldInfo *info,
386                   GIConstantInfo *branch,
387                   Xml         *file)
388 {
389   const gchar *name;
390   GIFieldInfoFlags flags;
391   gint size;
392   gint offset;
393   GITypeInfo *type;
394   GIBaseInfo *interface;
395   GIArgument value;
396
397   name = g_base_info_get_name ((GIBaseInfo *)info);
398   flags = g_field_info_get_flags (info);
399   size = g_field_info_get_size (info);
400   offset = g_field_info_get_offset (info);
401
402   xml_start_element (file, "field");
403   xml_printf (file, " name=\"%s\"", name);
404
405   /* Fields are assumed to be read-only
406    * (see also girwriter.py and girparser.c)
407    */
408   if (!(flags & GI_FIELD_IS_READABLE))
409     xml_printf (file, " readable=\"0\"");
410   if (flags & GI_FIELD_IS_WRITABLE)
411     xml_printf (file, " writable=\"1\"");
412
413   if (size)
414     xml_printf (file, " bits=\"%d\"", size);
415
416   write_attributes (file, (GIBaseInfo*) info);
417
418   type = g_field_info_get_type (info);
419
420   if (branch)
421     {
422       xml_printf (file, " branch=\"");
423       type = g_constant_info_get_type (branch);
424       g_constant_info_get_value (branch, &value);
425       write_constant_value (namespace, type, &value, file);
426       xml_printf (file, "\"");
427     }
428
429   if (file->show_all)
430     {
431       if (offset >= 0)
432         xml_printf (file, "offset=\"%d\"", offset);
433     }
434
435   interface = g_type_info_get_interface (type);
436   if (interface && g_base_info_get_type(interface) == GI_INFO_TYPE_CALLBACK)
437     write_callback_info (namespace, (GICallbackInfo *)interface, file);
438   else
439     write_type_info (namespace, type, file);
440
441   if (interface)
442     g_base_info_unref (interface);
443
444   g_base_info_unref ((GIBaseInfo *)type);
445
446   xml_end_element (file, "field");
447 }
448
449 static void
450 write_callable_info (const gchar    *namespace,
451                      GICallableInfo *info,
452                      Xml            *file)
453 {
454   GITypeInfo *type;
455   gint i;
456
457   write_attributes (file, (GIBaseInfo*) info);
458
459   type = g_callable_info_get_return_type (info);
460
461   xml_start_element (file, "return-value");
462
463   write_ownership_transfer (g_callable_info_get_caller_owns (info), file);
464
465   if (g_callable_info_may_return_null (info))
466     xml_printf (file, " allow-none=\"1\"");
467
468   if (g_callable_info_skip_return (info))
469     xml_printf (file, " skip=\"1\"");
470
471   write_return_value_attributes (file, info);
472
473   write_type_info (namespace, type, file);
474
475   xml_end_element (file, "return-value");
476
477   if (g_callable_info_get_n_args (info) <= 0)
478     return;
479
480   xml_start_element (file, "parameters");
481   for (i = 0; i < g_callable_info_get_n_args (info); i++)
482     {
483       GIArgInfo *arg = g_callable_info_get_arg (info, i);
484
485       xml_start_element (file, "parameter");
486       xml_printf (file, " name=\"%s\"",
487                   g_base_info_get_name ((GIBaseInfo *) arg));
488
489       write_ownership_transfer (g_arg_info_get_ownership_transfer (arg), file);
490
491       switch (g_arg_info_get_direction (arg))
492         {
493         case GI_DIRECTION_IN:
494           break;
495         case GI_DIRECTION_OUT:
496           xml_printf (file, " direction=\"out\" caller-allocates=\"%s\"",
497                       g_arg_info_is_caller_allocates (arg) ? "1" : "0");
498           break;
499         case GI_DIRECTION_INOUT:
500           xml_printf (file, " direction=\"inout\"");
501           break;
502         }
503
504       if (g_arg_info_may_be_null (arg))
505         xml_printf (file, " allow-none=\"1\"");
506
507       if (g_arg_info_is_return_value (arg))
508         xml_printf (file, " retval=\"1\"");
509
510       if (g_arg_info_is_optional (arg))
511         xml_printf (file, " optional=\"1\"");
512
513       switch (g_arg_info_get_scope (arg))
514         {
515         case GI_SCOPE_TYPE_INVALID:
516           break;
517         case GI_SCOPE_TYPE_CALL:
518           xml_printf (file, " scope=\"call\"");
519           break;
520         case GI_SCOPE_TYPE_ASYNC:
521           xml_printf (file, " scope=\"async\"");
522           break;
523         case GI_SCOPE_TYPE_NOTIFIED:
524           xml_printf (file, " scope=\"notified\"");
525           break;
526         }
527
528       if (g_arg_info_get_closure (arg) >= 0)
529         xml_printf (file, " closure=\"%d\"", g_arg_info_get_closure (arg));
530
531       if (g_arg_info_get_destroy (arg) >= 0)
532         xml_printf (file, " destroy=\"%d\"", g_arg_info_get_destroy (arg));
533
534       if (g_arg_info_is_skip (arg))
535         xml_printf (file, " skip=\"1\"");
536
537       write_attributes (file, (GIBaseInfo*) arg);
538
539       type = g_arg_info_get_type (arg);
540       write_type_info (namespace, type, file);
541
542       xml_end_element (file, "parameter");
543
544       g_base_info_unref ((GIBaseInfo *)arg);
545     }
546
547   xml_end_element (file, "parameters");
548   g_base_info_unref ((GIBaseInfo *)type);
549 }
550
551 static void
552 write_function_info (const gchar    *namespace,
553                      GIFunctionInfo *info,
554                      Xml            *file)
555 {
556   GIFunctionInfoFlags flags;
557   const gchar *tag;
558   const gchar *name;
559   const gchar *symbol;
560   gboolean deprecated;
561   gboolean throws;
562
563   flags = g_function_info_get_flags (info);
564   name = g_base_info_get_name ((GIBaseInfo *)info);
565   symbol = g_function_info_get_symbol (info);
566   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
567   throws = flags & GI_FUNCTION_THROWS;
568
569   if (flags & GI_FUNCTION_IS_CONSTRUCTOR)
570     tag = "constructor";
571   else if (flags & GI_FUNCTION_IS_METHOD)
572     tag = "method";
573   else
574     tag = "function";
575
576   xml_start_element (file, tag);
577   xml_printf (file, " name=\"%s\" c:identifier=\"%s\"",
578               name, symbol);
579
580   if (flags & GI_FUNCTION_IS_SETTER)
581     xml_printf (file, " type=\"setter\"");
582   else if (flags & GI_FUNCTION_IS_GETTER)
583     xml_printf (file, " type=\"getter\"");
584
585   if (deprecated)
586     xml_printf (file, " deprecated=\"1\"");
587
588   if (throws)
589     xml_printf (file, " throws=\"1\"");
590
591   write_callable_info (namespace, (GICallableInfo*)info, file);
592   xml_end_element (file, tag);
593 }
594
595 static void
596 write_callback_info (const gchar    *namespace,
597                      GICallbackInfo *info,
598                      Xml            *file)
599 {
600   const gchar *name;
601   gboolean deprecated;
602
603   name = g_base_info_get_name ((GIBaseInfo *)info);
604   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
605
606   xml_start_element (file, "callback");
607   xml_printf (file, " name=\"%s\"", name);
608
609   if (deprecated)
610     xml_printf (file, " deprecated=\"1\"");
611
612   write_callable_info (namespace, (GICallableInfo*)info, file);
613   xml_end_element (file, "callback");
614 }
615
616 static void
617 write_struct_info (const gchar  *namespace,
618                    GIStructInfo *info,
619                    Xml          *file)
620 {
621   const gchar *name;
622   const gchar *type_name;
623   const gchar *type_init;
624   gboolean deprecated;
625   gboolean is_gtype_struct;
626   gboolean foreign;
627   gint i;
628   gint size;
629   int n_elts;
630
631   name = g_base_info_get_name ((GIBaseInfo *)info);
632   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
633
634   type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
635   type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
636
637   if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_BOXED)
638     {
639       xml_start_element (file, "glib:boxed");
640       xml_printf (file, " glib:name=\"%s\"", name);
641     }
642   else
643     {
644       xml_start_element (file, "record");
645       xml_printf (file, " name=\"%s\"", name);
646     }
647
648   if (type_name != NULL)
649     xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init);
650
651   if (deprecated)
652     xml_printf (file, " deprecated=\"1\"");
653
654   is_gtype_struct = g_struct_info_is_gtype_struct (info);
655   if (is_gtype_struct)
656     xml_printf (file, " glib:is-gtype-struct=\"1\"");
657
658   write_attributes (file, (GIBaseInfo*) info);
659
660   size = g_struct_info_get_size (info);
661   if (file->show_all && size >= 0)
662     xml_printf (file, " size=\"%d\"", size);
663
664   foreign = g_struct_info_is_foreign (info);
665   if (foreign)
666     xml_printf (file, " foreign=\"1\"");
667
668   n_elts = g_struct_info_get_n_fields (info) + g_struct_info_get_n_methods (info);
669   if (n_elts > 0)
670     {
671       for (i = 0; i < g_struct_info_get_n_fields (info); i++)
672         {
673           GIFieldInfo *field = g_struct_info_get_field (info, i);
674           write_field_info (namespace, field, NULL, file);
675           g_base_info_unref ((GIBaseInfo *)field);
676         }
677
678       for (i = 0; i < g_struct_info_get_n_methods (info); i++)
679         {
680           GIFunctionInfo *function = g_struct_info_get_method (info, i);
681           write_function_info (namespace, function, file);
682           g_base_info_unref ((GIBaseInfo *)function);
683         }
684
685     }
686
687   xml_end_element_unchecked (file);
688 }
689
690 static void
691 write_value_info (const gchar *namespace,
692                   GIValueInfo *info,
693                   Xml         *file)
694 {
695   const gchar *name;
696   gint64 value;
697   gchar *value_str;
698   gboolean deprecated;
699
700   name = g_base_info_get_name ((GIBaseInfo *)info);
701   value = g_value_info_get_value (info);
702   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
703
704   xml_start_element (file, "member");
705   value_str = g_strdup_printf ("%" G_GINT64_FORMAT, value);
706   xml_printf (file, " name=\"%s\" value=\"%s\"", name, value_str);
707   g_free (value_str);
708
709   if (deprecated)
710     xml_printf (file, " deprecated=\"1\"");
711
712   write_attributes (file, (GIBaseInfo*) info);
713
714   xml_end_element (file, "member");
715 }
716
717 static void
718 write_constant_value (const gchar *namespace,
719                       GITypeInfo *type,
720                       GIArgument  *value,
721                       Xml        *file)
722 {
723   switch (g_type_info_get_tag (type))
724     {
725     case GI_TYPE_TAG_BOOLEAN:
726       xml_printf (file, "%d", value->v_boolean);
727       break;
728     case GI_TYPE_TAG_INT8:
729       xml_printf (file, "%d", value->v_int8);
730       break;
731     case GI_TYPE_TAG_UINT8:
732       xml_printf (file, "%d", value->v_uint8);
733       break;
734     case GI_TYPE_TAG_INT16:
735       xml_printf (file, "%" G_GINT16_FORMAT, value->v_int16);
736       break;
737     case GI_TYPE_TAG_UINT16:
738       xml_printf (file, "%" G_GUINT16_FORMAT, value->v_uint16);
739       break;
740     case GI_TYPE_TAG_INT32:
741       xml_printf (file, "%" G_GINT32_FORMAT, value->v_int32);
742       break;
743     case GI_TYPE_TAG_UINT32:
744       xml_printf (file, "%" G_GUINT32_FORMAT, value->v_uint32);
745       break;
746     case GI_TYPE_TAG_INT64:
747       xml_printf (file, "%" G_GINT64_FORMAT, value->v_int64);
748       break;
749     case GI_TYPE_TAG_UINT64:
750       xml_printf (file, "%" G_GUINT64_FORMAT, value->v_uint64);
751       break;
752     case GI_TYPE_TAG_FLOAT:
753       xml_printf (file, "%f", value->v_float);
754       break;
755     case GI_TYPE_TAG_DOUBLE:
756       xml_printf (file, "%f", value->v_double);
757       break;
758     case GI_TYPE_TAG_UTF8:
759     case GI_TYPE_TAG_FILENAME:
760       xml_printf (file, "%s", value->v_string);
761       break;
762     default:
763       g_assert_not_reached ();
764     }
765 }
766
767 static void
768 write_constant_info (const gchar    *namespace,
769                      GIConstantInfo *info,
770                      Xml            *file)
771 {
772   GITypeInfo *type;
773   const gchar *name;
774   GIArgument value;
775
776   name = g_base_info_get_name ((GIBaseInfo *)info);
777
778   xml_start_element (file, "constant");
779   xml_printf (file, " name=\"%s\"", name);
780
781   type = g_constant_info_get_type (info);
782   xml_printf (file, " value=\"");
783
784   g_constant_info_get_value (info, &value);
785   write_constant_value (namespace, type, &value, file);
786   xml_printf (file, "\"");
787
788   write_type_info (namespace, type, file);
789
790   write_attributes (file, (GIBaseInfo*) info);
791
792   xml_end_element (file, "constant");
793
794   g_base_info_unref ((GIBaseInfo *)type);
795 }
796
797
798 static void
799 write_enum_info (const gchar *namespace,
800                  GIEnumInfo *info,
801                  Xml         *file)
802 {
803   const gchar *name;
804   const gchar *type_name;
805   const gchar *type_init;
806   const gchar *error_domain;
807   gboolean deprecated;
808   gint i;
809
810   name = g_base_info_get_name ((GIBaseInfo *)info);
811   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
812
813   type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
814   type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
815   error_domain = g_enum_info_get_error_domain (info);
816
817   if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_ENUM)
818     xml_start_element (file, "enumeration");
819   else
820     xml_start_element (file, "bitfield");
821   xml_printf (file, " name=\"%s\"", name);
822
823   if (type_init)
824     xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init);
825   if (error_domain)
826     xml_printf (file, " glib:error-domain=\"%s\"", error_domain);
827
828   if (deprecated)
829     xml_printf (file, " deprecated=\"1\"");
830
831   write_attributes (file, (GIBaseInfo*) info);
832
833   for (i = 0; i < g_enum_info_get_n_values (info); i++)
834     {
835       GIValueInfo *value = g_enum_info_get_value (info, i);
836       write_value_info (namespace, value, file);
837       g_base_info_unref ((GIBaseInfo *)value);
838     }
839
840   xml_end_element_unchecked (file);
841 }
842
843 static void
844 write_signal_info (const gchar  *namespace,
845                    GISignalInfo *info,
846                    Xml          *file)
847 {
848   GSignalFlags flags;
849   const gchar *name;
850   gboolean deprecated;
851
852   name = g_base_info_get_name ((GIBaseInfo *)info);
853   flags = g_signal_info_get_flags (info);
854   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
855
856   xml_start_element (file, "glib:signal");
857   xml_printf (file, " name=\"%s\"", name);
858
859   if (deprecated)
860     xml_printf (file, " deprecated=\"1\"");
861
862   if (flags & G_SIGNAL_RUN_FIRST)
863     xml_printf (file, " when=\"FIRST\"");
864   else if (flags & G_SIGNAL_RUN_LAST)
865     xml_printf (file, " when=\"LAST\"");
866   else if (flags & G_SIGNAL_RUN_CLEANUP)
867     xml_printf (file, " when=\"CLEANUP\"");
868
869   if (flags & G_SIGNAL_NO_RECURSE)
870     xml_printf (file, " no-recurse=\"1\"");
871
872   if (flags & G_SIGNAL_DETAILED)
873     xml_printf (file, " detailed=\"1\"");
874
875   if (flags & G_SIGNAL_ACTION)
876     xml_printf (file, " action=\"1\"");
877
878   if (flags & G_SIGNAL_NO_HOOKS)
879     xml_printf (file, " no-hooks=\"1\"");
880
881   write_callable_info (namespace, (GICallableInfo*)info, file);
882
883   xml_end_element (file, "glib:signal");
884 }
885
886 static void
887 write_vfunc_info (const gchar *namespace,
888                   GIVFuncInfo *info,
889                   Xml         *file)
890 {
891   GIVFuncInfoFlags flags;
892   const gchar *name;
893   GIFunctionInfo *invoker;
894   gboolean deprecated;
895   gint offset;
896
897   name = g_base_info_get_name ((GIBaseInfo *)info);
898   flags = g_vfunc_info_get_flags (info);
899   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
900   offset = g_vfunc_info_get_offset (info);
901   invoker = g_vfunc_info_get_invoker (info);
902
903   xml_start_element (file, "virtual-method");
904   xml_printf (file, " name=\"%s\"", name);
905
906   if (deprecated)
907     xml_printf (file, " deprecated=\"1\"");
908
909   if (flags & GI_VFUNC_MUST_CHAIN_UP)
910     xml_printf (file, " must-chain-up=\"1\"");
911
912   if (flags & GI_VFUNC_MUST_OVERRIDE)
913     xml_printf (file, " override=\"always\"");
914   else if (flags & GI_VFUNC_MUST_NOT_OVERRIDE)
915     xml_printf (file, " override=\"never\"");
916
917   if (flags & GI_VFUNC_THROWS)
918     xml_printf (file, " throws=\"1\"");
919
920   xml_printf (file, " offset=\"%d\"", offset);
921
922   if (invoker)
923     xml_printf (file, " invoker=\"%s\"", g_base_info_get_name ((GIBaseInfo*)invoker));
924
925   write_callable_info (namespace, (GICallableInfo*)info, file);
926
927   xml_end_element (file, "virtual-method");
928 }
929
930 static void
931 write_property_info (const gchar    *namespace,
932                      GIPropertyInfo *info,
933                      Xml            *file)
934 {
935   GParamFlags flags;
936   const gchar *name;
937   gboolean deprecated;
938   GITypeInfo *type;
939
940   name = g_base_info_get_name ((GIBaseInfo *)info);
941   flags = g_property_info_get_flags (info);
942   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
943
944   xml_start_element (file, "property");
945   xml_printf (file, " name=\"%s\"", name);
946
947   if (deprecated)
948     xml_printf (file, " deprecated=\"1\"");
949
950   /* Properties are assumed to be read-only (see also girwriter.py) */
951   if (!(flags & G_PARAM_READABLE))
952     xml_printf (file, " readable=\"0\"");
953   if (flags & G_PARAM_WRITABLE)
954     xml_printf (file, " writable=\"1\"");
955
956   if (flags & G_PARAM_CONSTRUCT)
957     xml_printf (file, " construct=\"1\"");
958
959   if (flags & G_PARAM_CONSTRUCT_ONLY)
960     xml_printf (file, " construct-only=\"1\"");
961
962   write_ownership_transfer (g_property_info_get_ownership_transfer (info), file);
963
964   write_attributes (file, (GIBaseInfo*) info);
965
966   type = g_property_info_get_type (info);
967
968   write_type_info (namespace, type, file);
969
970   xml_end_element (file, "property");
971 }
972
973 static void
974 write_object_info (const gchar  *namespace,
975                    GIObjectInfo *info,
976                    Xml          *file)
977 {
978   const gchar *name;
979   const gchar *type_name;
980   const gchar *type_init;
981   const gchar *func;
982   gboolean deprecated;
983   gboolean is_abstract;
984   gboolean is_fundamental;
985   GIObjectInfo *pnode;
986   GIStructInfo *class_struct;
987   gint i;
988
989   name = g_base_info_get_name ((GIBaseInfo *)info);
990   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
991   is_abstract = g_object_info_get_abstract (info);
992   is_fundamental = g_object_info_get_fundamental (info);
993
994   type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
995   type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
996   xml_start_element (file, "class");
997   xml_printf (file, " name=\"%s\"", name);
998
999   pnode = g_object_info_get_parent (info);
1000   if (pnode)
1001     {
1002       write_type_name_attribute (namespace, (GIBaseInfo *)pnode, "parent", file);
1003       g_base_info_unref ((GIBaseInfo *)pnode);
1004     }
1005
1006   class_struct = g_object_info_get_class_struct (info);
1007   if (class_struct)
1008     {
1009       write_type_name_attribute (namespace, (GIBaseInfo*) class_struct, "glib:type-struct", file);
1010       g_base_info_unref ((GIBaseInfo*)class_struct);
1011     }
1012
1013   if (is_abstract)
1014     xml_printf (file, " abstract=\"1\"");
1015
1016   xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init);
1017
1018   if (is_fundamental)
1019     xml_printf (file, " glib:fundamental=\"1\"");
1020
1021   func = g_object_info_get_unref_function (info);
1022   if (func)
1023     xml_printf (file, " glib:unref-function=\"%s\"", func);
1024
1025   func = g_object_info_get_ref_function (info);
1026   if (func)
1027     xml_printf (file, " glib:ref-function=\"%s\"", func);
1028
1029   func = g_object_info_get_set_value_function (info);
1030   if (func)
1031     xml_printf (file, " glib:set-value-function=\"%s\"", func);
1032
1033   func = g_object_info_get_get_value_function (info);
1034   if (func)
1035     xml_printf (file, " glib:get-value-function=\"%s\"", func);
1036
1037   if (deprecated)
1038     xml_printf (file, " deprecated=\"1\"");
1039
1040   write_attributes (file, (GIBaseInfo*) info);
1041
1042   if (g_object_info_get_n_interfaces (info) > 0)
1043     {
1044       for (i = 0; i < g_object_info_get_n_interfaces (info); i++)
1045         {
1046           GIInterfaceInfo *imp = g_object_info_get_interface (info, i);
1047           xml_start_element (file, "implements");
1048           write_type_name_attribute (namespace, (GIBaseInfo *)imp, "name", file);
1049           xml_end_element (file, "implements");
1050           g_base_info_unref ((GIBaseInfo*)imp);
1051         }
1052     }
1053
1054   for (i = 0; i < g_object_info_get_n_fields (info); i++)
1055     {
1056       GIFieldInfo *field = g_object_info_get_field (info, i);
1057       write_field_info (namespace, field, NULL, file);
1058       g_base_info_unref ((GIBaseInfo *)field);
1059     }
1060
1061   for (i = 0; i < g_object_info_get_n_methods (info); i++)
1062     {
1063       GIFunctionInfo *function = g_object_info_get_method (info, i);
1064       write_function_info (namespace, function, file);
1065       g_base_info_unref ((GIBaseInfo *)function);
1066     }
1067
1068   for (i = 0; i < g_object_info_get_n_properties (info); i++)
1069     {
1070       GIPropertyInfo *prop = g_object_info_get_property (info, i);
1071       write_property_info (namespace, prop, file);
1072       g_base_info_unref ((GIBaseInfo *)prop);
1073     }
1074
1075   for (i = 0; i < g_object_info_get_n_signals (info); i++)
1076     {
1077       GISignalInfo *signal = g_object_info_get_signal (info, i);
1078       write_signal_info (namespace, signal, file);
1079       g_base_info_unref ((GIBaseInfo *)signal);
1080     }
1081
1082   for (i = 0; i < g_object_info_get_n_vfuncs (info); i++)
1083     {
1084       GIVFuncInfo *vfunc = g_object_info_get_vfunc (info, i);
1085       write_vfunc_info (namespace, vfunc, file);
1086       g_base_info_unref ((GIBaseInfo *)vfunc);
1087     }
1088
1089   for (i = 0; i < g_object_info_get_n_constants (info); i++)
1090     {
1091       GIConstantInfo *constant = g_object_info_get_constant (info, i);
1092       write_constant_info (namespace, constant, file);
1093       g_base_info_unref ((GIBaseInfo *)constant);
1094     }
1095
1096   xml_end_element (file, "class");
1097 }
1098
1099 static void
1100 write_interface_info (const gchar     *namespace,
1101                       GIInterfaceInfo *info,
1102                       Xml             *file)
1103 {
1104   const gchar *name;
1105   const gchar *type_name;
1106   const gchar *type_init;
1107   GIStructInfo *class_struct;
1108   gboolean deprecated;
1109   gint i;
1110
1111   name = g_base_info_get_name ((GIBaseInfo *)info);
1112   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
1113
1114   type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
1115   type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
1116   xml_start_element (file, "interface");
1117   xml_printf (file, " name=\"%s\" glib:type-name=\"%s\" glib:get-type=\"%s\"",
1118              name, type_name, type_init);
1119
1120   class_struct = g_interface_info_get_iface_struct (info);
1121   if (class_struct)
1122     {
1123       write_type_name_attribute (namespace, (GIBaseInfo*) class_struct, "glib:type-struct", file);
1124       g_base_info_unref ((GIBaseInfo*)class_struct);
1125     }
1126
1127   if (deprecated)
1128     xml_printf (file, " deprecated=\"1\"");
1129
1130   write_attributes (file, (GIBaseInfo*) info);
1131
1132   if (g_interface_info_get_n_prerequisites (info) > 0)
1133     {
1134       for (i = 0; i < g_interface_info_get_n_prerequisites (info); i++)
1135         {
1136           GIBaseInfo *req = g_interface_info_get_prerequisite (info, i);
1137
1138           xml_start_element (file, "prerequisite");
1139           write_type_name_attribute (namespace, req, "name", file);
1140
1141           xml_end_element_unchecked (file);
1142           g_base_info_unref (req);
1143         }
1144     }
1145
1146   for (i = 0; i < g_interface_info_get_n_methods (info); i++)
1147     {
1148       GIFunctionInfo *function = g_interface_info_get_method (info, i);
1149       write_function_info (namespace, function, file);
1150       g_base_info_unref ((GIBaseInfo *)function);
1151     }
1152
1153   for (i = 0; i < g_interface_info_get_n_properties (info); i++)
1154     {
1155       GIPropertyInfo *prop = g_interface_info_get_property (info, i);
1156       write_property_info (namespace, prop, file);
1157       g_base_info_unref ((GIBaseInfo *)prop);
1158     }
1159
1160   for (i = 0; i < g_interface_info_get_n_signals (info); i++)
1161     {
1162       GISignalInfo *signal = g_interface_info_get_signal (info, i);
1163       write_signal_info (namespace, signal, file);
1164       g_base_info_unref ((GIBaseInfo *)signal);
1165     }
1166
1167   for (i = 0; i < g_interface_info_get_n_vfuncs (info); i++)
1168     {
1169       GIVFuncInfo *vfunc = g_interface_info_get_vfunc (info, i);
1170       write_vfunc_info (namespace, vfunc, file);
1171       g_base_info_unref ((GIBaseInfo *)vfunc);
1172     }
1173
1174   for (i = 0; i < g_interface_info_get_n_constants (info); i++)
1175     {
1176       GIConstantInfo *constant = g_interface_info_get_constant (info, i);
1177       write_constant_info (namespace, constant, file);
1178       g_base_info_unref ((GIBaseInfo *)constant);
1179     }
1180
1181   xml_end_element (file, "interface");
1182 }
1183
1184 static void
1185 write_union_info (const gchar *namespace,
1186                   GIUnionInfo *info,
1187                   Xml         *file)
1188 {
1189   const gchar *name;
1190   const gchar *type_name;
1191   const gchar *type_init;
1192   gboolean deprecated;
1193   gint i;
1194   gint size;
1195
1196   name = g_base_info_get_name ((GIBaseInfo *)info);
1197   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
1198
1199   type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
1200   type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
1201
1202   xml_start_element (file, "union");
1203   xml_printf (file, " name=\"%s\"", name);
1204
1205   if (type_name)
1206     xml_printf (file, " type-name=\"%s\" get-type=\"%s\"", type_name, type_init);
1207
1208   if (deprecated)
1209     xml_printf (file, " deprecated=\"1\"");
1210
1211   size = g_union_info_get_size (info);
1212   if (file->show_all && size >= 0)
1213     xml_printf (file, " size=\"%d\"", size);
1214
1215   write_attributes (file, (GIBaseInfo*) info);
1216
1217   if (g_union_info_is_discriminated (info))
1218     {
1219       gint offset;
1220       GITypeInfo *type;
1221
1222       offset = g_union_info_get_discriminator_offset (info);
1223       type = g_union_info_get_discriminator_type (info);
1224
1225       xml_start_element (file, "discriminator");
1226       xml_printf (file, " offset=\"%d\" type=\"", offset);
1227       write_type_info (namespace, type, file);
1228       xml_end_element (file, "discriminator");
1229       g_base_info_unref ((GIBaseInfo *)type);
1230     }
1231
1232   for (i = 0; i < g_union_info_get_n_fields (info); i++)
1233     {
1234       GIFieldInfo *field = g_union_info_get_field (info, i);
1235       GIConstantInfo *constant = g_union_info_get_discriminator (info, i);
1236       write_field_info (namespace, field, constant, file);
1237       g_base_info_unref ((GIBaseInfo *)field);
1238       if (constant)
1239         g_base_info_unref ((GIBaseInfo *)constant);
1240     }
1241
1242   for (i = 0; i < g_union_info_get_n_methods (info); i++)
1243     {
1244       GIFunctionInfo *function = g_union_info_get_method (info, i);
1245       write_function_info (namespace, function, file);
1246       g_base_info_unref ((GIBaseInfo *)function);
1247     }
1248
1249   xml_end_element (file, "union");
1250 }
1251
1252
1253 /**
1254  * gir_writer_write:
1255  * @filename: filename to write to
1256  * @namespace: GIR namespace to write
1257  * @needs_prefix: if the filename needs prefixing
1258  * @show_all: if field size calculations should be included
1259  *
1260  * Writes the output of a typelib represented by @namespace
1261  * into a GIR xml file named @filename.
1262  */
1263 void
1264 gir_writer_write (const char *filename,
1265                   const char *namespace,
1266                   gboolean    needs_prefix,
1267                   gboolean    show_all)
1268 {
1269   FILE *ofile;
1270   gint i, j;
1271   char **dependencies;
1272   GIRepository *repository;
1273   Xml *xml;
1274
1275   repository = g_irepository_get_default ();
1276
1277   if (filename == NULL)
1278     ofile = stdout;
1279   else
1280     {
1281       gchar *full_filename;
1282
1283       if (needs_prefix)
1284         full_filename = g_strdup_printf ("%s-%s", namespace, filename);
1285       else
1286         full_filename = g_strdup (filename);
1287       ofile = g_fopen (filename, "w");
1288
1289       if (ofile == NULL)
1290         {
1291           g_fprintf (stderr, "failed to open '%s': %s\n",
1292                      full_filename, g_strerror (errno));
1293           g_free (full_filename);
1294
1295           return;
1296         }
1297
1298       g_free (full_filename);
1299     }
1300
1301   xml = xml_open (ofile);
1302   xml->show_all = show_all;
1303   xml_printf (xml, "<?xml version=\"1.0\"?>\n");
1304   xml_start_element (xml, "repository");
1305   xml_printf (xml, " version=\"1.0\"\n"
1306               "            xmlns=\"http://www.gtk.org/introspection/core/1.0\"\n"
1307               "            xmlns:c=\"http://www.gtk.org/introspection/c/1.0\"\n"
1308               "            xmlns:glib=\"http://www.gtk.org/introspection/glib/1.0\"");
1309
1310   dependencies = g_irepository_get_immediate_dependencies (repository,
1311                                                            namespace);
1312   if (dependencies != NULL)
1313     {
1314       for (i = 0; dependencies[i]; i++)
1315         {
1316           char **parts = g_strsplit (dependencies[i], "-", 2);
1317           xml_start_element (xml, "include");
1318           xml_printf (xml, " name=\"%s\" version=\"%s\"", parts[0], parts[1]);
1319           xml_end_element (xml, "include");
1320           g_strfreev (parts);
1321         }
1322     }
1323
1324   if (TRUE)
1325     {
1326       const gchar *shared_library;
1327       const gchar *c_prefix;
1328       const char *ns = namespace;
1329       const char *version;
1330       gint n_infos;
1331
1332       version = g_irepository_get_version (repository, ns);
1333
1334       shared_library = g_irepository_get_shared_library (repository, ns);
1335       c_prefix = g_irepository_get_c_prefix (repository, ns);
1336       xml_start_element (xml, "namespace");
1337       xml_printf (xml, " name=\"%s\" version=\"%s\"", ns, version);
1338       if (shared_library)
1339         xml_printf (xml, " shared-library=\"%s\"", shared_library);
1340       if (c_prefix)
1341         xml_printf (xml, " c:prefix=\"%s\"", c_prefix);
1342
1343       n_infos = g_irepository_get_n_infos (repository, ns);
1344       for (j = 0; j < n_infos; j++)
1345         {
1346           GIBaseInfo *info = g_irepository_get_info (repository, ns, j);
1347           switch (g_base_info_get_type (info))
1348             {
1349             case GI_INFO_TYPE_FUNCTION:
1350               write_function_info (ns, (GIFunctionInfo *)info, xml);
1351               break;
1352
1353             case GI_INFO_TYPE_CALLBACK:
1354               write_callback_info (ns, (GICallbackInfo *)info, xml);
1355               break;
1356
1357             case GI_INFO_TYPE_STRUCT:
1358             case GI_INFO_TYPE_BOXED:
1359               write_struct_info (ns, (GIStructInfo *)info, xml);
1360               break;
1361
1362             case GI_INFO_TYPE_UNION:
1363               write_union_info (ns, (GIUnionInfo *)info, xml);
1364               break;
1365
1366             case GI_INFO_TYPE_ENUM:
1367             case GI_INFO_TYPE_FLAGS:
1368               write_enum_info (ns, (GIEnumInfo *)info, xml);
1369               break;
1370
1371             case GI_INFO_TYPE_CONSTANT:
1372               write_constant_info (ns, (GIConstantInfo *)info, xml);
1373               break;
1374
1375             case GI_INFO_TYPE_OBJECT:
1376               write_object_info (ns, (GIObjectInfo *)info, xml);
1377               break;
1378
1379             case GI_INFO_TYPE_INTERFACE:
1380               write_interface_info (ns, (GIInterfaceInfo *)info, xml);
1381               break;
1382
1383             default:
1384               g_error ("unknown info type %d\n", g_base_info_get_type (info));
1385             }
1386
1387           g_base_info_unref (info);
1388         }
1389
1390       xml_end_element (xml, "namespace");
1391     }
1392
1393   xml_end_element (xml, "repository");
1394
1395   xml_free (xml);
1396 }