Branch and submit for IVI panda
[profile/ivi/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   gboolean deprecated;
775   GIArgument value;
776
777   name = g_base_info_get_name ((GIBaseInfo *)info);
778   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
779
780   xml_start_element (file, "constant");
781   xml_printf (file, " name=\"%s\"", name);
782
783   type = g_constant_info_get_type (info);
784   xml_printf (file, " value=\"");
785
786   g_constant_info_get_value (info, &value);
787   write_constant_value (namespace, type, &value, file);
788   xml_printf (file, "\"");
789
790   write_type_info (namespace, type, file);
791
792   write_attributes (file, (GIBaseInfo*) info);
793
794   xml_end_element (file, "constant");
795
796   g_base_info_unref ((GIBaseInfo *)type);
797 }
798
799
800 static void
801 write_enum_info (const gchar *namespace,
802                  GIEnumInfo *info,
803                  Xml         *file)
804 {
805   const gchar *name;
806   const gchar *type_name;
807   const gchar *type_init;
808   const gchar *error_domain;
809   gboolean deprecated;
810   gint i;
811
812   name = g_base_info_get_name ((GIBaseInfo *)info);
813   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
814
815   type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
816   type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
817   error_domain = g_enum_info_get_error_domain (info);
818
819   if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_ENUM)
820     xml_start_element (file, "enumeration");
821   else
822     xml_start_element (file, "bitfield");
823   xml_printf (file, " name=\"%s\"", name);
824
825   if (type_init)
826     xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init);
827   if (error_domain)
828     xml_printf (file, " glib:error-domain=\"%s\"", error_domain);
829
830   if (deprecated)
831     xml_printf (file, " deprecated=\"1\"");
832
833   write_attributes (file, (GIBaseInfo*) info);
834
835   for (i = 0; i < g_enum_info_get_n_values (info); i++)
836     {
837       GIValueInfo *value = g_enum_info_get_value (info, i);
838       write_value_info (namespace, value, file);
839       g_base_info_unref ((GIBaseInfo *)value);
840     }
841
842   xml_end_element_unchecked (file);
843 }
844
845 static void
846 write_signal_info (const gchar  *namespace,
847                    GISignalInfo *info,
848                    Xml          *file)
849 {
850   GSignalFlags flags;
851   const gchar *name;
852   gboolean deprecated;
853
854   name = g_base_info_get_name ((GIBaseInfo *)info);
855   flags = g_signal_info_get_flags (info);
856   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
857
858   xml_start_element (file, "glib:signal");
859   xml_printf (file, " name=\"%s\"", name);
860
861   if (deprecated)
862     xml_printf (file, " deprecated=\"1\"");
863
864   if (flags & G_SIGNAL_RUN_FIRST)
865     xml_printf (file, " when=\"FIRST\"");
866   else if (flags & G_SIGNAL_RUN_LAST)
867     xml_printf (file, " when=\"LAST\"");
868   else if (flags & G_SIGNAL_RUN_CLEANUP)
869     xml_printf (file, " when=\"CLEANUP\"");
870
871   if (flags & G_SIGNAL_NO_RECURSE)
872     xml_printf (file, " no-recurse=\"1\"");
873
874   if (flags & G_SIGNAL_DETAILED)
875     xml_printf (file, " detailed=\"1\"");
876
877   if (flags & G_SIGNAL_ACTION)
878     xml_printf (file, " action=\"1\"");
879
880   if (flags & G_SIGNAL_NO_HOOKS)
881     xml_printf (file, " no-hooks=\"1\"");
882
883   write_callable_info (namespace, (GICallableInfo*)info, file);
884
885   xml_end_element (file, "glib:signal");
886 }
887
888 static void
889 write_vfunc_info (const gchar *namespace,
890                   GIVFuncInfo *info,
891                   Xml         *file)
892 {
893   GIVFuncInfoFlags flags;
894   const gchar *name;
895   GIFunctionInfo *invoker;
896   gboolean deprecated;
897   gint offset;
898
899   name = g_base_info_get_name ((GIBaseInfo *)info);
900   flags = g_vfunc_info_get_flags (info);
901   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
902   offset = g_vfunc_info_get_offset (info);
903   invoker = g_vfunc_info_get_invoker (info);
904
905   xml_start_element (file, "virtual-method");
906   xml_printf (file, " name=\"%s\"", name);
907
908   if (deprecated)
909     xml_printf (file, " deprecated=\"1\"");
910
911   if (flags & GI_VFUNC_MUST_CHAIN_UP)
912     xml_printf (file, " must-chain-up=\"1\"");
913
914   if (flags & GI_VFUNC_MUST_OVERRIDE)
915     xml_printf (file, " override=\"always\"");
916   else if (flags & GI_VFUNC_MUST_NOT_OVERRIDE)
917     xml_printf (file, " override=\"never\"");
918
919   if (flags & GI_VFUNC_THROWS)
920     xml_printf (file, " throws=\"1\"");
921
922   xml_printf (file, " offset=\"%d\"", offset);
923
924   if (invoker)
925     xml_printf (file, " invoker=\"%s\"", g_base_info_get_name ((GIBaseInfo*)invoker));
926
927   write_callable_info (namespace, (GICallableInfo*)info, file);
928
929   xml_end_element (file, "virtual-method");
930 }
931
932 static void
933 write_property_info (const gchar    *namespace,
934                      GIPropertyInfo *info,
935                      Xml            *file)
936 {
937   GParamFlags flags;
938   const gchar *name;
939   gboolean deprecated;
940   GITypeInfo *type;
941
942   name = g_base_info_get_name ((GIBaseInfo *)info);
943   flags = g_property_info_get_flags (info);
944   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
945
946   xml_start_element (file, "property");
947   xml_printf (file, " name=\"%s\"", name);
948
949   if (deprecated)
950     xml_printf (file, " deprecated=\"1\"");
951
952   /* Properties are assumed to be read-only (see also girwriter.py) */
953   if (!(flags & G_PARAM_READABLE))
954     xml_printf (file, " readable=\"0\"");
955   if (flags & G_PARAM_WRITABLE)
956     xml_printf (file, " writable=\"1\"");
957
958   if (flags & G_PARAM_CONSTRUCT)
959     xml_printf (file, " construct=\"1\"");
960
961   if (flags & G_PARAM_CONSTRUCT_ONLY)
962     xml_printf (file, " construct-only=\"1\"");
963
964   write_ownership_transfer (g_property_info_get_ownership_transfer (info), file);
965
966   write_attributes (file, (GIBaseInfo*) info);
967
968   type = g_property_info_get_type (info);
969
970   write_type_info (namespace, type, file);
971
972   xml_end_element (file, "property");
973 }
974
975 static void
976 write_object_info (const gchar  *namespace,
977                    GIObjectInfo *info,
978                    Xml          *file)
979 {
980   const gchar *name;
981   const gchar *type_name;
982   const gchar *type_init;
983   const gchar *func;
984   gboolean deprecated;
985   gboolean is_abstract;
986   gboolean is_fundamental;
987   GIObjectInfo *pnode;
988   GIStructInfo *class_struct;
989   gint i;
990
991   name = g_base_info_get_name ((GIBaseInfo *)info);
992   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
993   is_abstract = g_object_info_get_abstract (info);
994   is_fundamental = g_object_info_get_fundamental (info);
995
996   type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
997   type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
998   xml_start_element (file, "class");
999   xml_printf (file, " name=\"%s\"", name);
1000
1001   pnode = g_object_info_get_parent (info);
1002   if (pnode)
1003     {
1004       write_type_name_attribute (namespace, (GIBaseInfo *)pnode, "parent", file);
1005       g_base_info_unref ((GIBaseInfo *)pnode);
1006     }
1007
1008   class_struct = g_object_info_get_class_struct (info);
1009   if (class_struct)
1010     {
1011       write_type_name_attribute (namespace, (GIBaseInfo*) class_struct, "glib:type-struct", file);
1012       g_base_info_unref ((GIBaseInfo*)class_struct);
1013     }
1014
1015   if (is_abstract)
1016     xml_printf (file, " abstract=\"1\"");
1017
1018   xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init);
1019
1020   if (is_fundamental)
1021     xml_printf (file, " glib:fundamental=\"1\"");
1022
1023   func = g_object_info_get_unref_function (info);
1024   if (func)
1025     xml_printf (file, " glib:unref-function=\"%s\"", func);
1026
1027   func = g_object_info_get_ref_function (info);
1028   if (func)
1029     xml_printf (file, " glib:ref-function=\"%s\"", func);
1030
1031   func = g_object_info_get_set_value_function (info);
1032   if (func)
1033     xml_printf (file, " glib:set-value-function=\"%s\"", func);
1034
1035   func = g_object_info_get_get_value_function (info);
1036   if (func)
1037     xml_printf (file, " glib:get-value-function=\"%s\"", func);
1038
1039   if (deprecated)
1040     xml_printf (file, " deprecated=\"1\"");
1041
1042   write_attributes (file, (GIBaseInfo*) info);
1043
1044   if (g_object_info_get_n_interfaces (info) > 0)
1045     {
1046       for (i = 0; i < g_object_info_get_n_interfaces (info); i++)
1047         {
1048           GIInterfaceInfo *imp = g_object_info_get_interface (info, i);
1049           xml_start_element (file, "implements");
1050           write_type_name_attribute (namespace, (GIBaseInfo *)imp, "name", file);
1051           xml_end_element (file, "implements");
1052           g_base_info_unref ((GIBaseInfo*)imp);
1053         }
1054     }
1055
1056   for (i = 0; i < g_object_info_get_n_fields (info); i++)
1057     {
1058       GIFieldInfo *field = g_object_info_get_field (info, i);
1059       write_field_info (namespace, field, NULL, file);
1060       g_base_info_unref ((GIBaseInfo *)field);
1061     }
1062
1063   for (i = 0; i < g_object_info_get_n_methods (info); i++)
1064     {
1065       GIFunctionInfo *function = g_object_info_get_method (info, i);
1066       write_function_info (namespace, function, file);
1067       g_base_info_unref ((GIBaseInfo *)function);
1068     }
1069
1070   for (i = 0; i < g_object_info_get_n_properties (info); i++)
1071     {
1072       GIPropertyInfo *prop = g_object_info_get_property (info, i);
1073       write_property_info (namespace, prop, file);
1074       g_base_info_unref ((GIBaseInfo *)prop);
1075     }
1076
1077   for (i = 0; i < g_object_info_get_n_signals (info); i++)
1078     {
1079       GISignalInfo *signal = g_object_info_get_signal (info, i);
1080       write_signal_info (namespace, signal, file);
1081       g_base_info_unref ((GIBaseInfo *)signal);
1082     }
1083
1084   for (i = 0; i < g_object_info_get_n_vfuncs (info); i++)
1085     {
1086       GIVFuncInfo *vfunc = g_object_info_get_vfunc (info, i);
1087       write_vfunc_info (namespace, vfunc, file);
1088       g_base_info_unref ((GIBaseInfo *)vfunc);
1089     }
1090
1091   for (i = 0; i < g_object_info_get_n_constants (info); i++)
1092     {
1093       GIConstantInfo *constant = g_object_info_get_constant (info, i);
1094       write_constant_info (namespace, constant, file);
1095       g_base_info_unref ((GIBaseInfo *)constant);
1096     }
1097
1098   xml_end_element (file, "class");
1099 }
1100
1101 static void
1102 write_interface_info (const gchar     *namespace,
1103                       GIInterfaceInfo *info,
1104                       Xml             *file)
1105 {
1106   const gchar *name;
1107   const gchar *type_name;
1108   const gchar *type_init;
1109   GIStructInfo *class_struct;
1110   gboolean deprecated;
1111   gint i;
1112
1113   name = g_base_info_get_name ((GIBaseInfo *)info);
1114   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
1115
1116   type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
1117   type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
1118   xml_start_element (file, "interface");
1119   xml_printf (file, " name=\"%s\" glib:type-name=\"%s\" glib:get-type=\"%s\"",
1120              name, type_name, type_init);
1121
1122   class_struct = g_interface_info_get_iface_struct (info);
1123   if (class_struct)
1124     {
1125       write_type_name_attribute (namespace, (GIBaseInfo*) class_struct, "glib:type-struct", file);
1126       g_base_info_unref ((GIBaseInfo*)class_struct);
1127     }
1128
1129   if (deprecated)
1130     xml_printf (file, " deprecated=\"1\"");
1131
1132   write_attributes (file, (GIBaseInfo*) info);
1133
1134   if (g_interface_info_get_n_prerequisites (info) > 0)
1135     {
1136       for (i = 0; i < g_interface_info_get_n_prerequisites (info); i++)
1137         {
1138           GIBaseInfo *req = g_interface_info_get_prerequisite (info, i);
1139
1140           xml_start_element (file, "prerequisite");
1141           write_type_name_attribute (namespace, req, "name", file);
1142
1143           xml_end_element_unchecked (file);
1144           g_base_info_unref (req);
1145         }
1146     }
1147
1148   for (i = 0; i < g_interface_info_get_n_methods (info); i++)
1149     {
1150       GIFunctionInfo *function = g_interface_info_get_method (info, i);
1151       write_function_info (namespace, function, file);
1152       g_base_info_unref ((GIBaseInfo *)function);
1153     }
1154
1155   for (i = 0; i < g_interface_info_get_n_properties (info); i++)
1156     {
1157       GIPropertyInfo *prop = g_interface_info_get_property (info, i);
1158       write_property_info (namespace, prop, file);
1159       g_base_info_unref ((GIBaseInfo *)prop);
1160     }
1161
1162   for (i = 0; i < g_interface_info_get_n_signals (info); i++)
1163     {
1164       GISignalInfo *signal = g_interface_info_get_signal (info, i);
1165       write_signal_info (namespace, signal, file);
1166       g_base_info_unref ((GIBaseInfo *)signal);
1167     }
1168
1169   for (i = 0; i < g_interface_info_get_n_vfuncs (info); i++)
1170     {
1171       GIVFuncInfo *vfunc = g_interface_info_get_vfunc (info, i);
1172       write_vfunc_info (namespace, vfunc, file);
1173       g_base_info_unref ((GIBaseInfo *)vfunc);
1174     }
1175
1176   for (i = 0; i < g_interface_info_get_n_constants (info); i++)
1177     {
1178       GIConstantInfo *constant = g_interface_info_get_constant (info, i);
1179       write_constant_info (namespace, constant, file);
1180       g_base_info_unref ((GIBaseInfo *)constant);
1181     }
1182
1183   xml_end_element (file, "interface");
1184 }
1185
1186 static void
1187 write_union_info (const gchar *namespace,
1188                   GIUnionInfo *info,
1189                   Xml         *file)
1190 {
1191   const gchar *name;
1192   const gchar *type_name;
1193   const gchar *type_init;
1194   gboolean deprecated;
1195   gint i;
1196   gint size;
1197
1198   name = g_base_info_get_name ((GIBaseInfo *)info);
1199   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
1200
1201   type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
1202   type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
1203
1204   xml_start_element (file, "union");
1205   xml_printf (file, " name=\"%s\"", name);
1206
1207   if (type_name)
1208     xml_printf (file, " type-name=\"%s\" get-type=\"%s\"", type_name, type_init);
1209
1210   if (deprecated)
1211     xml_printf (file, " deprecated=\"1\"");
1212
1213   size = g_union_info_get_size (info);
1214   if (file->show_all && size >= 0)
1215     xml_printf (file, " size=\"%d\"", size);
1216
1217   write_attributes (file, (GIBaseInfo*) info);
1218
1219   if (g_union_info_is_discriminated (info))
1220     {
1221       gint offset;
1222       GITypeInfo *type;
1223
1224       offset = g_union_info_get_discriminator_offset (info);
1225       type = g_union_info_get_discriminator_type (info);
1226
1227       xml_start_element (file, "discriminator");
1228       xml_printf (file, " offset=\"%d\" type=\"", offset);
1229       write_type_info (namespace, type, file);
1230       xml_end_element (file, "discriminator");
1231       g_base_info_unref ((GIBaseInfo *)type);
1232     }
1233
1234   for (i = 0; i < g_union_info_get_n_fields (info); i++)
1235     {
1236       GIFieldInfo *field = g_union_info_get_field (info, i);
1237       GIConstantInfo *constant = g_union_info_get_discriminator (info, i);
1238       write_field_info (namespace, field, constant, file);
1239       g_base_info_unref ((GIBaseInfo *)field);
1240       if (constant)
1241         g_base_info_unref ((GIBaseInfo *)constant);
1242     }
1243
1244   for (i = 0; i < g_union_info_get_n_methods (info); i++)
1245     {
1246       GIFunctionInfo *function = g_union_info_get_method (info, i);
1247       write_function_info (namespace, function, file);
1248       g_base_info_unref ((GIBaseInfo *)function);
1249     }
1250
1251   xml_end_element (file, "union");
1252 }
1253
1254
1255 /**
1256  * gir_writer_write:
1257  * @filename: filename to write to
1258  * @namespace: GIR namespace to write
1259  * @needs_prefix: if the filename needs prefixing
1260  * @show_all: if field size calculations should be included
1261  *
1262  * Writes the output of a typelib represented by @namespace
1263  * into a GIR xml file named @filename.
1264  */
1265 void
1266 gir_writer_write (const char *filename,
1267                   const char *namespace,
1268                   gboolean    needs_prefix,
1269                   gboolean    show_all)
1270 {
1271   FILE *ofile;
1272   gint i, j;
1273   char **dependencies;
1274   GIRepository *repository;
1275   Xml *xml;
1276
1277   repository = g_irepository_get_default ();
1278
1279   if (filename == NULL)
1280     ofile = stdout;
1281   else
1282     {
1283       gchar *full_filename;
1284
1285       if (needs_prefix)
1286         full_filename = g_strdup_printf ("%s-%s", namespace, filename);
1287       else
1288         full_filename = g_strdup (filename);
1289       ofile = g_fopen (filename, "w");
1290
1291       if (ofile == NULL)
1292         {
1293           g_fprintf (stderr, "failed to open '%s': %s\n",
1294                      full_filename, g_strerror (errno));
1295           g_free (full_filename);
1296
1297           return;
1298         }
1299
1300       g_free (full_filename);
1301     }
1302
1303   xml = xml_open (ofile);
1304   xml->show_all = show_all;
1305   xml_printf (xml, "<?xml version=\"1.0\"?>\n");
1306   xml_start_element (xml, "repository");
1307   xml_printf (xml, " version=\"1.0\"\n"
1308               "            xmlns=\"http://www.gtk.org/introspection/core/1.0\"\n"
1309               "            xmlns:c=\"http://www.gtk.org/introspection/c/1.0\"\n"
1310               "            xmlns:glib=\"http://www.gtk.org/introspection/glib/1.0\"");
1311
1312   dependencies = g_irepository_get_dependencies (repository,
1313                                                  namespace);
1314   if (dependencies != NULL)
1315     {
1316       for (i = 0; dependencies[i]; i++)
1317         {
1318           char **parts = g_strsplit (dependencies[i], "-", 2);
1319           xml_start_element (xml, "include");
1320           xml_printf (xml, " name=\"%s\" version=\"%s\"", parts[0], parts[1]);
1321           xml_end_element (xml, "include");
1322           g_strfreev (parts);
1323         }
1324     }
1325
1326   if (TRUE)
1327     {
1328       const gchar *shared_library;
1329       const gchar *c_prefix;
1330       const char *ns = namespace;
1331       const char *version;
1332       gint n_infos;
1333
1334       version = g_irepository_get_version (repository, ns);
1335
1336       shared_library = g_irepository_get_shared_library (repository, ns);
1337       c_prefix = g_irepository_get_c_prefix (repository, ns);
1338       xml_start_element (xml, "namespace");
1339       xml_printf (xml, " name=\"%s\" version=\"%s\"", ns, version);
1340       if (shared_library)
1341         xml_printf (xml, " shared-library=\"%s\"", shared_library);
1342       if (c_prefix)
1343         xml_printf (xml, " c:prefix=\"%s\"", c_prefix);
1344
1345       n_infos = g_irepository_get_n_infos (repository, ns);
1346       for (j = 0; j < n_infos; j++)
1347         {
1348           GIBaseInfo *info = g_irepository_get_info (repository, ns, j);
1349           switch (g_base_info_get_type (info))
1350             {
1351             case GI_INFO_TYPE_FUNCTION:
1352               write_function_info (ns, (GIFunctionInfo *)info, xml);
1353               break;
1354
1355             case GI_INFO_TYPE_CALLBACK:
1356               write_callback_info (ns, (GICallbackInfo *)info, xml);
1357               break;
1358
1359             case GI_INFO_TYPE_STRUCT:
1360             case GI_INFO_TYPE_BOXED:
1361               write_struct_info (ns, (GIStructInfo *)info, xml);
1362               break;
1363
1364             case GI_INFO_TYPE_UNION:
1365               write_union_info (ns, (GIUnionInfo *)info, xml);
1366               break;
1367
1368             case GI_INFO_TYPE_ENUM:
1369             case GI_INFO_TYPE_FLAGS:
1370               write_enum_info (ns, (GIEnumInfo *)info, xml);
1371               break;
1372
1373             case GI_INFO_TYPE_CONSTANT:
1374               write_constant_info (ns, (GIConstantInfo *)info, xml);
1375               break;
1376
1377             case GI_INFO_TYPE_OBJECT:
1378               write_object_info (ns, (GIObjectInfo *)info, xml);
1379               break;
1380
1381             case GI_INFO_TYPE_INTERFACE:
1382               write_interface_info (ns, (GIInterfaceInfo *)info, xml);
1383               break;
1384
1385             default:
1386               g_error ("unknown info type %d\n", g_base_info_get_type (info));
1387             }
1388
1389           g_base_info_unref (info);
1390         }
1391
1392       xml_end_element (xml, "namespace");
1393     }
1394
1395   xml_end_element (xml, "repository");
1396
1397   xml_free (xml);
1398 }