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