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