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