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