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