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