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