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