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