Fix up g-ir-generate for new include= syntax
[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   if (flags & G_PARAM_READABLE)
846     xml_printf (file, " readable=\"1\"");
847   else
848     xml_printf (file, " readable=\"0\"");
849
850   if (flags & G_PARAM_WRITABLE)
851     xml_printf (file, " writable=\"1\"");
852   else
853     xml_printf (file, " writable=\"0\"");
854
855   if (flags & G_PARAM_CONSTRUCT)
856     xml_printf (file, " construct=\"1\"");
857
858   if (flags & G_PARAM_CONSTRUCT_ONLY)
859     xml_printf (file, " construct-only=\"1\"");
860     
861   type = g_property_info_get_type (info);
862
863   write_type_info (namespace, type, file);
864
865   xml_end_element (file, "property");
866 }
867
868 static void
869 write_object_info (const gchar  *namespace, 
870                    GIObjectInfo *info,
871                    Xml          *file)
872 {
873   const gchar *name;
874   const gchar *type_name;
875   const gchar *type_init;
876   gboolean deprecated;
877   GIObjectInfo *pnode;
878   gint i;
879
880   name = g_base_info_get_name ((GIBaseInfo *)info);
881   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
882   
883   type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
884   type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
885   xml_start_element (file, "class");
886   xml_printf (file, " name=\"%s\"", name);
887
888   pnode = g_object_info_get_parent (info);
889   if (pnode)
890     {
891       write_type_name_attribute (namespace, (GIBaseInfo *)pnode, "parent", file);
892       g_base_info_unref ((GIBaseInfo *)pnode);
893     }
894
895   xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init);
896
897   if (deprecated)
898     xml_printf (file, " deprecated=\"1\"");
899         
900
901   if (g_object_info_get_n_interfaces (info) > 0)
902     {
903       for (i = 0; i < g_object_info_get_n_interfaces (info); i++)
904         {
905           GIInterfaceInfo *imp = g_object_info_get_interface (info, i);
906           xml_start_element (file, "implements");
907           write_type_name_attribute (namespace, (GIBaseInfo *)imp, "name", file);
908           xml_end_element (file, "implements");
909           g_base_info_unref ((GIBaseInfo*)imp);
910         }
911     }
912
913   for (i = 0; i < g_object_info_get_n_fields (info); i++)
914     {
915       GIFieldInfo *field = g_object_info_get_field (info, i);
916       write_field_info (namespace, field, NULL, file);
917       g_base_info_unref ((GIBaseInfo *)field);
918     }
919
920   for (i = 0; i < g_object_info_get_n_methods (info); i++)
921     {
922       GIFunctionInfo *function = g_object_info_get_method (info, i);
923       write_function_info (namespace, function, file);
924       g_base_info_unref ((GIBaseInfo *)function);
925     }
926
927   for (i = 0; i < g_object_info_get_n_properties (info); i++)
928     {
929       GIPropertyInfo *prop = g_object_info_get_property (info, i);
930       write_property_info (namespace, prop, file);
931       g_base_info_unref ((GIBaseInfo *)prop);
932     }
933
934   for (i = 0; i < g_object_info_get_n_signals (info); i++)
935     {
936       GISignalInfo *signal = g_object_info_get_signal (info, i);
937       write_signal_info (namespace, signal, file);
938       g_base_info_unref ((GIBaseInfo *)signal);
939     }
940   
941   for (i = 0; i < g_object_info_get_n_vfuncs (info); i++)
942     {
943       GIVFuncInfo *vfunc = g_object_info_get_vfunc (info, i);
944       write_vfunc_info (namespace, vfunc, file);
945       g_base_info_unref ((GIBaseInfo *)vfunc);
946     }
947
948   for (i = 0; i < g_object_info_get_n_constants (info); i++)
949     {
950       GIConstantInfo *constant = g_object_info_get_constant (info, i);
951       write_constant_info (namespace, constant, file);
952       g_base_info_unref ((GIBaseInfo *)constant);
953     }
954   
955   xml_end_element (file, "class");
956 }
957
958 static void
959 write_interface_info (const gchar     *namespace,
960                       GIInterfaceInfo *info,
961                       Xml             *file)
962 {
963   const gchar *name;
964   const gchar *type_name;
965   const gchar *type_init;
966   gboolean deprecated;
967   gint i;
968
969   name = g_base_info_get_name ((GIBaseInfo *)info);
970   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
971
972   type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
973   type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
974   xml_start_element (file, "interface");
975   xml_printf (file, " name=\"%s\" glib:type-name=\"%s\" glib:get-type=\"%s\"",
976              name, type_name, type_init);
977
978   if (deprecated)
979     xml_printf (file, " deprecated=\"1\"");
980         
981
982   if (g_interface_info_get_n_prerequisites (info) > 0)
983     {
984       xml_start_element (file, "requires");
985       for (i = 0; i < g_interface_info_get_n_prerequisites (info); i++)
986         {
987           GIBaseInfo *req = g_interface_info_get_prerequisite (info, i);
988           
989           if (g_base_info_get_type (req) == GI_INFO_TYPE_INTERFACE)
990             xml_start_element (file, "interface");
991           else
992             xml_start_element (file, "object");
993           write_type_name_attribute (namespace, req, "name", file);
994           xml_end_element_unchecked (file);
995           g_base_info_unref (req);
996         }
997       xml_end_element (file, "requires");
998     }
999
1000   for (i = 0; i < g_interface_info_get_n_methods (info); i++)
1001     {
1002       GIFunctionInfo *function = g_interface_info_get_method (info, i);
1003       write_function_info (namespace, function, file);
1004       g_base_info_unref ((GIBaseInfo *)function);
1005     }
1006
1007   for (i = 0; i < g_interface_info_get_n_properties (info); i++)
1008     {
1009       GIPropertyInfo *prop = g_interface_info_get_property (info, i);
1010       write_property_info (namespace, prop, file);
1011       g_base_info_unref ((GIBaseInfo *)prop);
1012     }
1013
1014   for (i = 0; i < g_interface_info_get_n_signals (info); i++)
1015     {
1016       GISignalInfo *signal = g_interface_info_get_signal (info, i);
1017       write_signal_info (namespace, signal, file);
1018       g_base_info_unref ((GIBaseInfo *)signal);
1019     }
1020   
1021   for (i = 0; i < g_interface_info_get_n_vfuncs (info); i++)
1022     {
1023       GIVFuncInfo *vfunc = g_interface_info_get_vfunc (info, i);
1024       write_vfunc_info (namespace, vfunc, file);
1025       g_base_info_unref ((GIBaseInfo *)vfunc);
1026     }
1027
1028   for (i = 0; i < g_interface_info_get_n_constants (info); i++)
1029     {
1030       GIConstantInfo *constant = g_interface_info_get_constant (info, i);
1031       write_constant_info (namespace, constant, file);
1032       g_base_info_unref ((GIBaseInfo *)constant);
1033     }
1034   
1035   xml_end_element (file, "interface");
1036 }
1037
1038 static void
1039 write_error_domain_info (const gchar       *namespace,
1040                          GIErrorDomainInfo *info,
1041                          Xml               *file)
1042 {
1043   GIBaseInfo *enum_;
1044   const gchar *name, *quark;
1045   
1046   name = g_base_info_get_name ((GIBaseInfo *)info);
1047   quark = g_error_domain_info_get_quark (info);
1048   enum_ = (GIBaseInfo *)g_error_domain_info_get_codes (info);
1049   xml_start_element (file, "errordomain");
1050   xml_printf (file, " name=\"%s\" get-quark=\"%s\"",
1051               name, quark);
1052   write_type_name_attribute (namespace, enum_, "codes", file);
1053   xml_end_element (file, "errordomain");
1054   g_base_info_unref (enum_);
1055 }
1056
1057 static void
1058 write_union_info (const gchar *namespace, 
1059                   GIUnionInfo *info, 
1060                   Xml         *file)
1061 {
1062   const gchar *name;
1063   const gchar *type_name;
1064   const gchar *type_init;
1065   gboolean deprecated;
1066   gint i;
1067
1068   name = g_base_info_get_name ((GIBaseInfo *)info);
1069   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
1070
1071   type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
1072   type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
1073   
1074   xml_start_element (file, "union");
1075   xml_printf (file, " name=\"%s\"", name);
1076   
1077   if (type_name)
1078     xml_printf (file, " type-name=\"%s\" get-type=\"%s\"", type_name, type_init);
1079           
1080   if (deprecated)
1081     xml_printf (file, " deprecated=\"1\"");
1082         
1083
1084   if (g_union_info_is_discriminated (info))
1085     {
1086       gint offset;
1087       GITypeInfo *type;
1088
1089       offset = g_union_info_get_discriminator_offset (info);
1090       type = g_union_info_get_discriminator_type (info);
1091       
1092       xml_start_element (file, "discriminator");
1093       xml_printf (file, " offset=\"%d\" type=\"", offset);
1094       write_type_info (namespace, type, file);
1095       xml_end_element (file, "discriminator");
1096       g_base_info_unref ((GIBaseInfo *)type);
1097     }
1098
1099   for (i = 0; i < g_union_info_get_n_fields (info); i++)
1100     {
1101       GIFieldInfo *field = g_union_info_get_field (info, i);
1102       GIConstantInfo *constant = g_union_info_get_discriminator (info, i);
1103       write_field_info (namespace, field, constant, file);
1104       g_base_info_unref ((GIBaseInfo *)field);
1105       if (constant)
1106         g_base_info_unref ((GIBaseInfo *)constant);
1107     }
1108
1109   for (i = 0; i < g_union_info_get_n_methods (info); i++)
1110     {
1111       GIFunctionInfo *function = g_union_info_get_method (info, i);
1112       write_function_info (namespace, function, file);
1113       g_base_info_unref ((GIBaseInfo *)function);
1114     }
1115
1116   xml_end_element (file, "union");
1117 }
1118
1119 static void
1120 write_repository (const char   *namespace,
1121                   gboolean      needs_prefix)
1122 {
1123   FILE *ofile;
1124   gchar *ns;
1125   gint i, j;
1126   char **dependencies;
1127   GIRepository *repository;
1128   Xml *xml;
1129
1130   repository = g_irepository_get_default ();
1131
1132   if (output == NULL)
1133     ofile = stdout;
1134   else
1135     {
1136       gchar *filename;
1137       
1138       if (needs_prefix)
1139         filename = g_strdup_printf ("%s-%s", namespace, output);  
1140       else
1141         filename = g_strdup (output);
1142       ofile = g_fopen (filename, "w");
1143       
1144       if (ofile == NULL)
1145         {
1146           g_fprintf (stderr, "failed to open '%s': %s\n",
1147                      filename, g_strerror (errno));
1148           g_free (filename);
1149           
1150           return;
1151         }
1152       
1153       g_free (filename);
1154     }
1155
1156   xml = xml_open (ofile);
1157   
1158   xml_printf (xml, "<?xml version=\"1.0\"?>\n");
1159   xml_start_element (xml, "repository");
1160   xml_printf (xml, " version=\"1.0\"\n"
1161               "            xmlns=\"http://www.gtk.org/introspection/core/1.0\"\n"
1162               "            xmlns:c=\"http://www.gtk.org/introspection/c/1.0\"\n"
1163               "            xmlns:glib=\"http://www.gtk.org/introspection/glib/1.0\"");
1164
1165   dependencies = g_irepository_get_dependencies (repository,
1166                                                  namespace);
1167   if (dependencies != NULL)
1168     {
1169       for (i = 0; dependencies[i]; i++)
1170         {
1171           char **parts = g_strsplit (dependencies[i], "-", 2);
1172           xml_start_element (xml, "include");
1173           xml_printf (xml, " name=\"%s\" version=\"%s\"", parts[0], parts[1]);
1174           xml_end_element (xml, "include");
1175           g_strfreev (parts);
1176         }
1177     }
1178
1179   if (TRUE)
1180     {
1181       const gchar *shared_library;
1182       const char *ns = namespace;
1183       const char *version;
1184
1185       version = g_irepository_get_version (repository, ns);
1186
1187       shared_library = g_irepository_get_shared_library (repository, ns);
1188       xml_start_element (xml, "namespace");
1189       xml_printf (xml, " name=\"%s\" version=\"%s\"", ns, version);
1190       if (shared_library)
1191         xml_printf (xml, " shared-library=\"%s\"", shared_library);
1192       
1193       for (j = 0; j < g_irepository_get_n_infos (repository, ns); j++)
1194         {
1195           GIBaseInfo *info = g_irepository_get_info (repository, ns, j);
1196           switch (g_base_info_get_type (info))
1197             {
1198             case GI_INFO_TYPE_FUNCTION:
1199               write_function_info (ns, (GIFunctionInfo *)info, xml);
1200               break;
1201               
1202             case GI_INFO_TYPE_CALLBACK:
1203               write_callback_info (ns, (GICallbackInfo *)info, xml);
1204               break;
1205
1206             case GI_INFO_TYPE_STRUCT:
1207             case GI_INFO_TYPE_BOXED:
1208               write_struct_info (ns, (GIStructInfo *)info, xml);
1209               break;
1210
1211             case GI_INFO_TYPE_UNION:
1212               write_union_info (ns, (GIUnionInfo *)info, xml);
1213               break;
1214
1215             case GI_INFO_TYPE_ENUM:
1216             case GI_INFO_TYPE_FLAGS:
1217               write_enum_info (ns, (GIEnumInfo *)info, xml);
1218               break;
1219               
1220             case GI_INFO_TYPE_CONSTANT:
1221               write_constant_info (ns, (GIConstantInfo *)info, xml);
1222               break;
1223
1224             case GI_INFO_TYPE_OBJECT:
1225               write_object_info (ns, (GIObjectInfo *)info, xml);
1226               break;
1227
1228             case GI_INFO_TYPE_INTERFACE:
1229               write_interface_info (ns, (GIInterfaceInfo *)info, xml);
1230               break;
1231
1232             case GI_INFO_TYPE_ERROR_DOMAIN:
1233               write_error_domain_info (ns, (GIErrorDomainInfo *)info, xml);
1234               break;
1235
1236             default:
1237               g_error ("unknown info type %d\n", g_base_info_get_type (info));
1238             }
1239
1240           g_base_info_unref (info);
1241         }
1242
1243       xml_end_element (xml, "namespace");
1244     }
1245
1246   xml_end_element (xml, "repository");
1247       
1248   xml_free (xml);
1249 }
1250
1251 static const guchar *
1252 load_typelib (const gchar  *filename,
1253                GModule     **dlhandle,
1254                gsize        *len)
1255 {
1256   guchar *typelib;
1257   gsize *typelib_size;
1258   GModule *handle; 
1259
1260   handle = g_module_open (filename, G_MODULE_BIND_LOCAL|G_MODULE_BIND_LAZY);
1261   if (handle == NULL)
1262     {
1263       g_printerr ("Could not load typelib from '%s': %s\n", 
1264                   filename, g_module_error ());
1265       return NULL;
1266     }
1267
1268   if (!g_module_symbol (handle, "_G_TYPELIB", (gpointer *) &typelib))
1269     {
1270       g_printerr ("Could not load typelib from '%s': %s\n", 
1271                   filename, g_module_error ());
1272       return NULL;
1273     }
1274   
1275   if (!g_module_symbol (handle, "_G_TYPELIB_SIZE", (gpointer *) &typelib_size))
1276     {
1277       g_printerr ("Could not load typelib from '%s': %s\n", 
1278                   filename, g_module_error ());
1279       return NULL;
1280     }
1281
1282   *len = *typelib_size;
1283   
1284   if (dlhandle)
1285     *dlhandle = handle;
1286
1287   return typelib;
1288 }
1289
1290 int 
1291 main (int argc, char *argv[])
1292 {  
1293   gboolean shlib = FALSE;
1294   gchar **input = NULL;
1295   GOptionContext *context;
1296   GError *error = NULL;
1297   gboolean needs_prefix;
1298   gint i;
1299   GTypelib *data;
1300   GOptionEntry options[] = 
1301     {
1302       { "shlib", 0, 0, G_OPTION_ARG_NONE, &shlib, "handle typelib embedded in shlib", NULL },
1303       { "output", 'o', 0, G_OPTION_ARG_FILENAME, &output, "output file", "FILE" }, 
1304       { "includedir", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &includedirs, "include directories in GIR search path", NULL }, 
1305       { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &input, NULL, NULL },
1306       { NULL, }
1307     };
1308
1309   g_log_set_always_fatal (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
1310
1311   g_type_init ();
1312
1313   g_typelib_check_sanity ();
1314
1315   context = g_option_context_new ("");
1316   g_option_context_add_main_entries (context, options, NULL);
1317   g_option_context_parse (context, &argc, &argv, &error);
1318
1319   if (!input) 
1320     { 
1321       g_fprintf (stderr, "no input files\n"); 
1322       
1323       return 1;
1324     }
1325
1326   if (includedirs != NULL)
1327     for (i = 0; includedirs[i]; i++)
1328       g_irepository_prepend_search_path (includedirs[i]);
1329
1330   for (i = 0; input[i]; i++)
1331     {
1332       GModule *dlhandle = NULL;
1333       const guchar *typelib;
1334       gsize len;
1335       const char *namespace;
1336
1337       if (!shlib)
1338         {
1339           if (!g_file_get_contents (input[i], (gchar **)&typelib, &len, &error))
1340             {
1341               g_fprintf (stderr, "failed to read '%s': %s\n", 
1342                          input[i], error->message);
1343               g_clear_error (&error);
1344               continue;
1345             }
1346         }
1347       else
1348         {
1349           typelib = load_typelib (input[i], &dlhandle, &len);
1350           if (!typelib)
1351             {
1352               g_fprintf (stderr, "failed to load typelib from '%s'\n", 
1353                          input[i]);
1354               continue;
1355             }
1356         }
1357
1358       if (input[i + 1] && output)
1359         needs_prefix = TRUE;
1360       else
1361         needs_prefix = FALSE;
1362
1363       data = g_typelib_new_from_const_memory (typelib, len);
1364       {
1365         GError *error = NULL;
1366         if (!g_typelib_validate (data, &error)) {
1367           g_printerr ("typelib not valid: %s\n", error->message);
1368           g_clear_error (&error);
1369           return 1;
1370         }
1371       }
1372       namespace = g_irepository_load_typelib (g_irepository_get_default (), data, 0,
1373                                               &error);
1374       if (namespace == NULL)
1375         {
1376           g_printerr ("failed to load typelib: %s\n", error->message);
1377           return 1;
1378         }
1379         
1380       write_repository (namespace, needs_prefix);
1381
1382       if (dlhandle)
1383         {
1384           g_module_close (dlhandle);
1385           dlhandle = NULL;
1386         }
1387
1388       /* when writing to stdout, stop after the first module */
1389       if (input[i + 1] && !output)
1390         {
1391           g_fprintf (stderr, "warning, %d modules omitted\n",
1392                      g_strv_length (input) - 1);
1393
1394           break;
1395         }
1396     }
1397       
1398   return 0;
1399 }