Bug 559705 – Missing association between static methods and classes
[gnome.gobject-introspection] / girepository / girparser.c
1 /* GObject introspection: A parser for the XML GIR format
2  *
3  * Copyright (C) 2008 Philip Van Hoof
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdio.h>
24
25 #include <glib.h>
26 #include "girparser.h"
27 #include "girmodule.h"
28 #include "girnode.h"
29 #include "gtypelib.h"
30
31 struct _GIrParser
32 {
33   gchar **includes;
34   GList *parsed_modules; /* All previously parsed modules */
35 };
36
37 typedef enum
38 {
39   STATE_START,    
40   STATE_END,        
41   STATE_REPOSITORY, 
42   STATE_INCLUDE,  
43   STATE_NAMESPACE,  
44   STATE_ENUM,      /* 5 */    
45   STATE_BITFIELD,  
46   STATE_FUNCTION,   
47   STATE_FUNCTION_RETURN, 
48   STATE_FUNCTION_PARAMETERS,
49   STATE_FUNCTION_PARAMETER,  /* 10 */
50   STATE_CLASS,  
51   STATE_CLASS_FIELD,
52   STATE_CLASS_PROPERTY,
53   STATE_INTERFACE,
54   STATE_INTERFACE_PROPERTY,   /* 15 */
55   STATE_INTERFACE_FIELD,
56   STATE_IMPLEMENTS, 
57   STATE_PREREQUISITE,
58   STATE_BOXED,  
59   STATE_BOXED_FIELD, /* 20 */
60   STATE_STRUCT,   
61   STATE_STRUCT_FIELD,
62   STATE_ERRORDOMAIN, 
63   STATE_UNION,
64   STATE_UNION_FIELD, /* 25 */
65   STATE_NAMESPACE_CONSTANT, 
66   STATE_CLASS_CONSTANT, 
67   STATE_INTERFACE_CONSTANT,
68   STATE_ALIAS,
69   STATE_TYPE
70 } ParseState;
71
72 typedef struct _ParseContext ParseContext;
73 struct _ParseContext
74 {
75   GIrParser *parser;
76
77   ParseState state;
78   ParseState prev_state;
79
80   GList *modules;
81   GList *include_modules;
82   GList *dependencies;
83   GHashTable *aliases;
84   GHashTable *disguised_structures;
85
86   const char *namespace;
87   GIrModule *current_module;
88   GIrNode *current_node;
89   GIrNode *current_typed;
90   gboolean is_varargs;
91   GList *type_stack;
92   GList *type_parameters;
93   int type_depth;
94 };
95
96 static void start_element_handler (GMarkupParseContext *context,
97                                    const gchar         *element_name,
98                                    const gchar        **attribute_names,
99                                    const gchar        **attribute_values,
100                                    gpointer             user_data,
101                                    GError             **error);
102 static void end_element_handler   (GMarkupParseContext *context,
103                                    const gchar         *element_name,
104                                    gpointer             user_data,
105                                    GError             **error);
106 static void text_handler          (GMarkupParseContext *context,
107                                    const gchar         *text,
108                                    gsize                text_len,
109                                    gpointer             user_data,
110                                    GError             **error);
111 static void cleanup               (GMarkupParseContext *context,
112                                    GError              *error,
113                                    gpointer             user_data);
114
115 static GMarkupParser markup_parser = 
116 {
117   start_element_handler,
118   end_element_handler,
119   text_handler,
120   NULL,
121   cleanup
122 };
123
124 static gboolean
125 start_alias (GMarkupParseContext *context,
126              const gchar         *element_name,
127              const gchar        **attribute_names,
128              const gchar        **attribute_values,
129              ParseContext        *ctx,
130              GError             **error);
131
132 static const gchar *find_attribute (const gchar  *name, 
133                                     const gchar **attribute_names,
134                                     const gchar **attribute_values);
135
136
137 GIrParser *
138 g_ir_parser_new (void)
139 {
140   GIrParser *parser = g_slice_new0 (GIrParser);
141
142   return parser;
143 }
144
145 void
146 g_ir_parser_free (GIrParser *parser)
147 {
148   GList *l;
149
150   if (parser->includes)
151     g_strfreev (parser->includes);
152
153   for (l = parser->parsed_modules; l; l = l->next)
154     g_ir_module_free (l->data);
155
156   g_slice_free (GIrParser, parser);
157 }
158
159 void
160 g_ir_parser_set_includes (GIrParser          *parser,
161                           const gchar *const *includes)
162 {
163   if (parser->includes)
164     g_strfreev (parser->includes);
165
166   parser->includes = g_strdupv ((char **)includes);
167 }
168
169 static void
170 firstpass_start_element_handler (GMarkupParseContext *context,
171                                  const gchar         *element_name,
172                                  const gchar        **attribute_names,
173                                  const gchar        **attribute_values,
174                                  gpointer             user_data,
175                                  GError             **error)
176 {
177   ParseContext *ctx = user_data;
178
179   if (strcmp (element_name, "alias") == 0) 
180     {
181       start_alias (context, element_name, attribute_names, attribute_values,
182                    ctx, error);
183     }
184   else if (strcmp (element_name, "record") == 0)
185     {
186       const gchar *name;
187       const gchar *disguised;
188
189       name = find_attribute ("name", attribute_names, attribute_values);
190       disguised = find_attribute ("disguised", attribute_names, attribute_values);
191
192       if (disguised && strcmp (disguised, "1") == 0)
193         {
194           char *key;
195
196           key = g_strdup_printf ("%s.%s", ctx->namespace, name);
197           g_hash_table_replace (ctx->disguised_structures, key, GINT_TO_POINTER (1));
198         }
199     }
200 }
201
202 static void
203 firstpass_end_element_handler (GMarkupParseContext *context,
204                                const gchar         *element_name,
205                                gpointer             user_data,
206                                GError             **error)
207 {
208 }
209
210 static GMarkupParser firstpass_parser = 
211 {
212   firstpass_start_element_handler,
213   firstpass_end_element_handler,
214   NULL,
215   NULL,
216   NULL,
217 };
218
219 static char *
220 locate_gir (GIrParser  *parser,
221             const char *name,
222             const char *version)
223 {
224   const gchar *const *datadirs;
225   const gchar *const *dir;
226   char *girname;
227   char *path = NULL;
228       
229   datadirs = g_get_system_data_dirs ();
230       
231   girname = g_strdup_printf ("%s-%s.gir", name, version);
232   
233   if (parser->includes != NULL)
234     {
235       for (dir = (const gchar *const *)parser->includes; *dir; dir++) 
236         {
237           path = g_build_filename (*dir, girname, NULL);
238           if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
239             return path;
240           g_free (path);
241           path = NULL;
242         }
243     }
244   for (dir = datadirs; *dir; dir++) 
245     {
246       path = g_build_filename (*dir, "gir", girname, NULL);
247       if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
248         return path;
249       g_free (path);
250       path = NULL;
251     }
252   g_free (girname);
253   return path;
254 }
255
256 #define MISSING_ATTRIBUTE(ctx,error,element,attribute)                          \
257   do {                                                                          \
258     int line_number, char_number;                                                \
259     g_markup_parse_context_get_position (context, &line_number, &char_number);  \
260     g_set_error (error,                                                         \
261                  G_MARKUP_ERROR,                                                \
262                  G_MARKUP_ERROR_INVALID_CONTENT,                                \
263                  "Line %d, character %d: The attribute '%s' on the element '%s' must be specified",    \
264                  line_number, char_number, attribute, element);         \
265   } while (0)
266
267 static void
268 backtrace_stderr (void)
269 {
270 #if defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS)
271   void *array[50];
272   int size;
273   char **strings;
274   size_t i;
275
276   size = backtrace (array, 50);
277   strings = (char**) backtrace_symbols (array, size);
278
279   fprintf (stderr, "--- BACKTRACE (%zd frames) ---\n", size);
280
281   for (i = 0; i < size; i++)
282     fprintf (stderr, "%s\n", strings[i]);
283
284   fprintf (stderr, "--- END BACKTRACE ---\n", size);
285
286   free (strings);
287 #endif
288 }
289
290
291 static const gchar *
292 find_attribute (const gchar  *name, 
293                 const gchar **attribute_names,
294                 const gchar **attribute_values)
295 {
296   gint i;
297   
298   for (i = 0; attribute_names[i] != NULL; i++)
299     if (strcmp (attribute_names[i], name) == 0)
300       return attribute_values[i];
301   
302   return 0;
303 }
304
305 static void
306 state_switch (ParseContext *ctx, ParseState newstate)
307 {
308   g_debug ("State: %d", newstate);
309   ctx->prev_state = ctx->state;
310   ctx->state = newstate;
311 }
312
313 static GIrNodeType * parse_type_internal (const gchar *str, gchar **next, gboolean in_glib,
314                                           gboolean in_gobject);
315
316 typedef struct {
317   const gchar *str;
318   gint tag;
319   gboolean pointer;
320 } BasicTypeInfo;
321
322 static BasicTypeInfo basic_types[] = {
323     { "none",     GI_TYPE_TAG_VOID,    0 },
324     { "any",      GI_TYPE_TAG_VOID,    1 },
325
326     { "bool",     GI_TYPE_TAG_BOOLEAN, 0 },
327     { "char",     GI_TYPE_TAG_INT8,    0 },
328     { "int8",     GI_TYPE_TAG_INT8,    0 },
329     { "uint8",    GI_TYPE_TAG_UINT8,   0 },
330     { "int16",    GI_TYPE_TAG_INT16,   0 },
331     { "uint16",   GI_TYPE_TAG_UINT16,  0 },
332     { "int32",    GI_TYPE_TAG_INT32,   0 },
333     { "uint32",   GI_TYPE_TAG_UINT32,  0 },
334     { "int64",    GI_TYPE_TAG_INT64,   0 },
335     { "uint64",   GI_TYPE_TAG_UINT64,  0 },
336     { "int",      GI_TYPE_TAG_INT,     0 },
337     { "uint",     GI_TYPE_TAG_UINT,    0 },
338     { "long",     GI_TYPE_TAG_LONG,    0 },
339     { "ulong",    GI_TYPE_TAG_ULONG,   0 },
340     { "ssize_t",  GI_TYPE_TAG_SSIZE,   0 },
341     { "ssize",    GI_TYPE_TAG_SSIZE,   0 },
342     { "size_t",   GI_TYPE_TAG_SIZE,    0 },
343     { "size",     GI_TYPE_TAG_SIZE,    0 },
344     { "float",    GI_TYPE_TAG_FLOAT,   0 },
345     { "double",   GI_TYPE_TAG_DOUBLE,  0 },
346     { "time_t",   GI_TYPE_TAG_TIME_T,  0 },
347     { "GType",    GI_TYPE_TAG_GTYPE,   0 },
348     { "utf8",     GI_TYPE_TAG_UTF8,    1 },  
349     { "filename", GI_TYPE_TAG_FILENAME,1 },
350 };  
351
352 static const BasicTypeInfo *
353 parse_basic (const char *str)
354 {
355   gint i;
356   gint n_basic = G_N_ELEMENTS (basic_types);
357   
358   for (i = 0; i < n_basic; i++)
359     {
360       if (g_str_has_prefix (str, basic_types[i].str))
361         return &(basic_types[i]);
362     }  
363   return NULL;
364 }
365
366 static GIrNodeType *
367 parse_type_internal (const gchar *str, char **next, gboolean in_glib,
368                      gboolean in_gobject)
369 {
370   const BasicTypeInfo *basic;  
371   GIrNodeType *type;
372   char *temporary_type = NULL;
373   
374   type = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
375   
376   type->unparsed = g_strdup (str);
377
378   /* See comment below on GLib.List handling */
379   if (in_gobject && strcmp (str, "Type") == 0) 
380     {
381       temporary_type = g_strdup ("GLib.Type");
382       str = temporary_type;
383     }
384   
385   basic = parse_basic (str);
386   if (basic != NULL)
387     {
388       type->is_basic = TRUE;
389       type->tag = basic->tag;
390       type->is_pointer = basic->pointer;
391
392       str += strlen(basic->str);
393     }
394   else if (in_glib)
395     {
396       /* If we're inside GLib, handle "List" etc. by prefixing with
397        * "GLib." so the parsing code below doesn't have to get more
398        * special. 
399        */
400       if (g_str_has_prefix (str, "List<") ||
401           strcmp (str, "List") == 0)
402         {
403           temporary_type = g_strdup_printf ("GLib.List%s", str + 4);
404           str = temporary_type;
405         }
406       else if (g_str_has_prefix (str, "SList<") ||
407           strcmp (str, "SList") == 0)
408         {
409           temporary_type = g_strdup_printf ("GLib.SList%s", str + 5);
410           str = temporary_type;
411         }
412       else if (g_str_has_prefix (str, "HashTable<") ||
413           strcmp (str, "HashTable") == 0)
414         {
415           temporary_type = g_strdup_printf ("GLib.HashTable%s", str + 9);
416           str = temporary_type;
417         }
418       else if (g_str_has_prefix (str, "Error<") ||
419           strcmp (str, "Error") == 0)
420         {
421           temporary_type = g_strdup_printf ("GLib.Error%s", str + 5);
422           str = temporary_type;
423         }
424     }
425
426   if (basic != NULL)
427     /* found a basic type */;
428   else if (g_str_has_prefix (str, "GLib.List") ||
429            g_str_has_prefix (str, "GLib.SList"))
430     {
431       str += strlen ("GLib.");
432       if (g_str_has_prefix (str, "List"))
433         {
434           type->tag = GI_TYPE_TAG_GLIST;
435           type->is_glist = TRUE;
436           type->is_pointer = TRUE;
437           str += strlen ("List");
438         }
439       else
440         {
441           type->tag = GI_TYPE_TAG_GSLIST;
442           type->is_gslist = TRUE;
443           type->is_pointer = TRUE;
444           str += strlen ("SList");
445         }
446     }
447   else if (g_str_has_prefix (str, "GLib.HashTable"))
448     {
449       str += strlen ("GLib.");
450
451       type->tag = GI_TYPE_TAG_GHASH;
452       type->is_ghashtable = TRUE;
453       type->is_pointer = TRUE;
454       str += strlen ("HashTable");
455     }
456   else if (g_str_has_prefix (str, "GLib.Error"))
457     {
458       str += strlen ("GLib.");
459
460       type->tag = GI_TYPE_TAG_ERROR;
461       type->is_error = TRUE;
462       type->is_pointer = TRUE;
463       str += strlen ("Error");
464       
465       if (*str == '<')
466         {
467           (str)++;
468           char *tmp, *end;
469           
470           end = strchr (str, '>');
471           tmp = g_strndup (str, end - str);
472           type->errors = g_strsplit (tmp, ",", 0);
473           g_free (tmp);
474
475           str = end;
476         }
477     }
478   else 
479     {
480       type->tag = GI_TYPE_TAG_INTERFACE;
481       type->is_interface = TRUE; 
482       const char *start = str;
483
484       /* must be an interface type */
485       while (g_ascii_isalnum (*str) || 
486              *str == '.' || 
487              *str == '-' || 
488              *str == '_' ||
489              *str == ':')
490         (str)++;
491
492       type->interface = g_strndup (start, str - start);
493     }
494   
495   if (next)
496     *next = (char*)str;
497   g_assert (type->tag >= 0 && type->tag <= GI_TYPE_TAG_ERROR);
498   g_free (temporary_type);
499   return type;
500
501 /* error: */
502   g_ir_node_free ((GIrNode *)type);
503   g_free (temporary_type);  
504   return NULL;
505 }
506
507 static const char *
508 resolve_aliases (ParseContext *ctx, const gchar *type)
509 {
510   gpointer orig;
511   gpointer value;
512   GSList *seen_values = NULL;
513   const gchar *lookup;
514   gchar *prefixed;
515
516   if (strchr (type, '.') == NULL)
517     {
518       prefixed = g_strdup_printf ("%s.%s", ctx->namespace, type);
519       lookup = prefixed;
520     }
521   else
522     {
523       lookup = type;
524       prefixed = NULL;
525     }
526
527   seen_values = g_slist_prepend (seen_values, (char*)lookup);
528   while (g_hash_table_lookup_extended (ctx->current_module->aliases, lookup, &orig, &value))
529     {
530       g_debug ("Resolved: %s => %s\n", lookup, (char*)value);
531       lookup = value;
532       if (g_slist_find_custom (seen_values, lookup,
533                                (GCompareFunc)strcmp) != NULL)
534         break;
535       seen_values = g_slist_prepend (seen_values, (gchar*)lookup);
536     }
537   g_slist_free (seen_values);
538
539   if (lookup == prefixed)
540     lookup = type;
541
542   g_free (prefixed);
543   
544   return lookup;
545 }
546
547 static gboolean
548 is_disguised_structure (ParseContext *ctx, const gchar *type)
549 {
550   const gchar *lookup;
551   gchar *prefixed;
552   gboolean result;
553
554   if (strchr (type, '.') == NULL)
555     {
556       prefixed = g_strdup_printf ("%s.%s", ctx->namespace, type);
557       lookup = prefixed;
558     }
559   else
560     {
561       lookup = type;
562       prefixed = NULL;
563     }
564
565   result = g_hash_table_lookup (ctx->current_module->disguised_structures,
566                                 lookup) != NULL;
567   
568   g_free (prefixed);
569   
570   return result;
571 }
572
573 static GIrNodeType *
574 parse_type (ParseContext *ctx, const gchar *type)
575 {
576   GIrNodeType *node;
577   const BasicTypeInfo *basic;
578   gboolean in_glib, in_gobject;
579
580   in_glib = strcmp (ctx->namespace, "GLib") == 0;
581   in_gobject = strcmp (ctx->namespace, "GObject") == 0;
582
583   /* Do not search aliases for basic types */
584   basic = parse_basic (type);
585   if (basic == NULL)
586     type = resolve_aliases (ctx, type);
587
588   node = parse_type_internal (type, NULL, in_glib, in_gobject);
589   if (node)
590     g_debug ("Parsed type: %s => %d", type, node->tag);
591   else
592     g_critical ("Failed to parse type: '%s'", type);
593
594   return node;
595 }
596
597 static gboolean
598 start_glib_boxed (GMarkupParseContext *context,
599                   const gchar         *element_name,
600                   const gchar        **attribute_names,
601                   const gchar        **attribute_values,
602                   ParseContext        *ctx,
603                   GError             **error)
604 {
605   const gchar *name;
606   const gchar *typename;
607   const gchar *typeinit;
608   const gchar *deprecated;
609   GIrNodeBoxed *boxed;
610
611   if (!(strcmp (element_name, "glib:boxed") == 0 &&
612         ctx->state == STATE_NAMESPACE))
613     return FALSE;
614
615   name = find_attribute ("glib:name", attribute_names, attribute_values);
616   typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
617   typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
618   deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
619   
620   if (name == NULL)
621     {
622       MISSING_ATTRIBUTE (context, error, element_name, "glib:name");
623       return FALSE;
624     }
625   else if (typename == NULL)
626     {
627       MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
628       return FALSE;
629     }
630   else if (typeinit == NULL)
631     {
632       MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
633       return FALSE;
634     }
635
636   boxed = (GIrNodeBoxed *) g_ir_node_new (G_IR_NODE_BOXED);
637           
638   ((GIrNode *)boxed)->name = g_strdup (name);
639   boxed->gtype_name = g_strdup (typename);
640   boxed->gtype_init = g_strdup (typeinit);
641   if (deprecated)
642     boxed->deprecated = TRUE;
643   else
644     boxed->deprecated = FALSE;
645           
646   ctx->current_node = (GIrNode *)boxed;
647   ctx->current_module->entries = 
648     g_list_append (ctx->current_module->entries, boxed);
649   
650   state_switch (ctx, STATE_BOXED);
651
652   return TRUE;
653 }
654
655 static gboolean
656 start_function (GMarkupParseContext *context,
657                 const gchar         *element_name,
658                 const gchar        **attribute_names,
659                 const gchar        **attribute_values,
660                 ParseContext        *ctx,
661                 GError             **error)
662 {
663   const gchar *name;
664   const gchar *symbol;
665   const gchar *deprecated;
666   const gchar *throws;
667   GIrNodeFunction *function;
668   gboolean found = FALSE;
669   
670   switch (ctx->state)
671     {
672     case STATE_NAMESPACE:
673       found = (strcmp (element_name, "function") == 0 ||
674                strcmp (element_name, "callback") == 0);
675       break;
676     case STATE_CLASS:
677       found = strcmp (element_name, "function") == 0;
678         /* fallthrough */
679     case STATE_BOXED:
680     case STATE_STRUCT:
681     case STATE_UNION:
682       found = (found || strcmp (element_name, "constructor") == 0);
683       /* fallthrough */
684     case STATE_INTERFACE:
685       found = (found ||
686                strcmp (element_name, "method") == 0 ||
687                strcmp (element_name, "callback") == 0);
688       break;
689     default:
690       break;
691     }
692
693   if (!found)
694     return FALSE;
695
696   name = find_attribute ("name", attribute_names, attribute_values);
697   symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
698   deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
699   throws = find_attribute ("throws", attribute_names, attribute_values);
700       
701   if (name == NULL)
702     {
703       MISSING_ATTRIBUTE (context, error, element_name, "name");
704       return FALSE;
705     }
706   else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
707     {
708       MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
709       return FALSE;
710     }
711
712   function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
713       
714   ((GIrNode *)function)->name = g_strdup (name);
715   function->symbol = g_strdup (symbol);
716   function->parameters = NULL;
717   if (deprecated)
718     function->deprecated = TRUE;
719   else
720     function->deprecated = FALSE;
721   
722   if (strcmp (element_name, "method") == 0 ||
723       strcmp (element_name, "constructor") == 0)
724     {
725       function->is_method = TRUE;
726       
727       if (strcmp (element_name, "constructor") == 0)
728         function->is_constructor = TRUE;
729       else
730         function->is_constructor = FALSE;
731     }
732   else
733     {
734       function->is_method = FALSE;
735       function->is_setter = FALSE;
736       function->is_getter = FALSE;
737       function->is_constructor = FALSE;
738       if (strcmp (element_name, "callback") == 0)
739         ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
740     }
741
742   if (throws && strcmp (throws, "1") == 0)
743     function->throws = TRUE;
744   else
745     function->throws = FALSE;
746
747   if (ctx->current_node == NULL)
748     {
749       ctx->current_module->entries = 
750         g_list_append (ctx->current_module->entries, function);       
751     }
752   else
753     switch (ctx->current_node->type)
754       {
755       case G_IR_NODE_INTERFACE:
756       case G_IR_NODE_OBJECT:
757         {
758           GIrNodeInterface *iface;
759           
760           iface = (GIrNodeInterface *)ctx->current_node;
761           iface->members = g_list_append (iface->members, function);
762         }
763         break;
764       case G_IR_NODE_BOXED:
765         {
766           GIrNodeBoxed *boxed;
767           
768           boxed = (GIrNodeBoxed *)ctx->current_node;
769           boxed->members = g_list_append (boxed->members, function);
770         }
771         break;
772       case G_IR_NODE_STRUCT:
773         {
774           GIrNodeStruct *struct_;
775           
776           struct_ = (GIrNodeStruct *)ctx->current_node;
777           struct_->members = g_list_append (struct_->members, function);                }
778         break;
779       case G_IR_NODE_UNION:
780         {
781           GIrNodeUnion *union_;
782           
783           union_ = (GIrNodeUnion *)ctx->current_node;
784           union_->members = g_list_append (union_->members, function);
785         }
786         break;
787       default:
788         g_assert_not_reached ();
789       }
790   
791   ctx->current_node = (GIrNode *)function;
792   state_switch (ctx, STATE_FUNCTION);
793   
794   return TRUE;
795 }
796
797 static void
798 parse_param_transfer (GIrNodeParam *param, const gchar *transfer)
799 {
800   if (transfer == NULL)
801   {
802     g_warning ("required attribute 'transfer-ownership' missing");
803   }
804   else if (strcmp (transfer, "none") == 0)
805     {
806       param->transfer = FALSE;
807       param->shallow_transfer = FALSE;
808     }
809   else if (strcmp (transfer, "container") == 0)
810     {
811       param->transfer = FALSE;
812       param->shallow_transfer = TRUE;
813     }
814   else if (strcmp (transfer, "full") == 0)
815     {
816       param->transfer = TRUE;
817       param->shallow_transfer = FALSE;
818     }
819   else
820     {
821       g_warning ("Unknown transfer-ownership value: %s", transfer);
822     }
823 }
824
825 static gboolean
826 start_parameter (GMarkupParseContext *context,
827                  const gchar         *element_name,
828                  const gchar        **attribute_names,
829                  const gchar        **attribute_values,
830                  ParseContext        *ctx,
831                  GError             **error)
832 {
833   const gchar *name;
834   const gchar *direction;
835   const gchar *retval;
836   const gchar *dipper;
837   const gchar *optional;
838   const gchar *allow_none;
839   const gchar *transfer;
840   GIrNodeParam *param;
841       
842   if (!(strcmp (element_name, "parameter") == 0 &&
843         ctx->state == STATE_FUNCTION_PARAMETERS))
844     return FALSE;
845
846   name = find_attribute ("name", attribute_names, attribute_values);
847   direction = find_attribute ("direction", attribute_names, attribute_values);
848   retval = find_attribute ("retval", attribute_names, attribute_values);
849   dipper = find_attribute ("dipper", attribute_names, attribute_values);
850   optional = find_attribute ("optional", attribute_names, attribute_values);
851   allow_none = find_attribute ("allow-none", attribute_names, attribute_values);
852   transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
853
854   if (name == NULL)
855     name = "unknown";
856
857   param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
858
859   ctx->current_typed = (GIrNode*) param;
860   ctx->current_typed->name = g_strdup (name);
861
862   state_switch (ctx, STATE_FUNCTION_PARAMETER);
863
864   if (direction && strcmp (direction, "out") == 0)
865     {
866       param->in = FALSE;
867       param->out = TRUE;
868     }
869   else if (direction && strcmp (direction, "inout") == 0)
870     {
871       param->in = TRUE;
872       param->out = TRUE;
873     }
874   else
875     {
876       param->in = TRUE;
877       param->out = FALSE;
878     }
879
880   if (retval && strcmp (retval, "1") == 0)
881     param->retval = TRUE;
882   else
883     param->retval = FALSE;
884
885   if (dipper && strcmp (dipper, "1") == 0)
886     param->dipper = TRUE;
887   else
888     param->dipper = FALSE;
889
890   if (optional && strcmp (optional, "1") == 0)
891     param->optional = TRUE;
892   else
893     param->optional = FALSE;
894
895   if (allow_none && strcmp (allow_none, "1") == 0)
896     param->allow_none = TRUE;
897   else
898     param->allow_none = FALSE;
899
900   parse_param_transfer (param, transfer);
901
902   ((GIrNode *)param)->name = g_strdup (name);
903           
904   switch (ctx->current_node->type)
905     {
906     case G_IR_NODE_FUNCTION:
907     case G_IR_NODE_CALLBACK:
908       {
909         GIrNodeFunction *func;
910
911         func = (GIrNodeFunction *)ctx->current_node;
912         func->parameters = g_list_append (func->parameters, param);
913       }
914       break;
915     case G_IR_NODE_SIGNAL:
916       {
917         GIrNodeSignal *signal;
918
919         signal = (GIrNodeSignal *)ctx->current_node;
920         signal->parameters = g_list_append (signal->parameters, param);
921       }
922       break;
923     case G_IR_NODE_VFUNC:
924       {
925         GIrNodeVFunc *vfunc;
926                 
927         vfunc = (GIrNodeVFunc *)ctx->current_node;
928         vfunc->parameters = g_list_append (vfunc->parameters, param);
929       }
930       break;
931     default:
932       g_assert_not_reached ();
933     }
934
935   return TRUE;
936 }
937
938 static gboolean
939 start_field (GMarkupParseContext *context,
940              const gchar         *element_name,
941              const gchar        **attribute_names,
942              const gchar        **attribute_values,
943              ParseContext        *ctx,
944              GError             **error)
945 {
946   const gchar *name;
947   const gchar *readable;
948   const gchar *writable;
949   const gchar *bits;
950   const gchar *branch;
951   GIrNodeField *field;
952
953   switch (ctx->state)
954     {
955     case STATE_CLASS:
956     case STATE_BOXED:
957     case STATE_STRUCT:
958     case STATE_UNION:
959     case STATE_INTERFACE:
960       break;
961     default:
962       return FALSE;
963     }
964   
965   if (strcmp (element_name, "field") != 0)
966     return FALSE;
967   
968   name = find_attribute ("name", attribute_names, attribute_values);
969   readable = find_attribute ("readable", attribute_names, attribute_values);
970   writable = find_attribute ("writable", attribute_names, attribute_values);
971   bits = find_attribute ("bits", attribute_names, attribute_values);
972   branch = find_attribute ("branch", attribute_names, attribute_values);
973   
974   if (name == NULL)
975     {
976       MISSING_ATTRIBUTE (context, error, element_name, "name");
977       return FALSE;
978     }
979
980   field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
981   ctx->current_typed = (GIrNode*) field;
982   ((GIrNode *)field)->name = g_strdup (name);
983   /* Fields are assumed to be read-only.
984    * (see also girwriter.py and generate.c)
985    */
986   field->readable = readable == NULL || strcmp (readable, "0") == 0;
987   field->writable = writable != NULL && strcmp (writable, "1") == 0;
988   
989   if (bits)
990     field->bits = atoi (bits);
991   else
992     field->bits = 0;
993   
994   switch (ctx->current_node->type)
995     {
996     case G_IR_NODE_OBJECT:
997       {
998         GIrNodeInterface *iface;
999         
1000         iface = (GIrNodeInterface *)ctx->current_node;
1001         iface->members = g_list_append (iface->members, field);
1002         state_switch (ctx, STATE_CLASS_FIELD);
1003       }
1004       break;
1005     case G_IR_NODE_INTERFACE:
1006       {
1007         GIrNodeInterface *iface;
1008         
1009         iface = (GIrNodeInterface *)ctx->current_node;
1010         iface->members = g_list_append (iface->members, field);
1011         state_switch (ctx, STATE_INTERFACE_FIELD);
1012       }
1013       break;
1014     case G_IR_NODE_BOXED:
1015       {
1016         GIrNodeBoxed *boxed;
1017         
1018         boxed = (GIrNodeBoxed *)ctx->current_node;
1019                 boxed->members = g_list_append (boxed->members, field);
1020                 state_switch (ctx, STATE_BOXED_FIELD);
1021       }
1022       break;
1023     case G_IR_NODE_STRUCT:
1024       {
1025         GIrNodeStruct *struct_;
1026         
1027         struct_ = (GIrNodeStruct *)ctx->current_node;
1028         struct_->members = g_list_append (struct_->members, field);
1029         state_switch (ctx, STATE_STRUCT_FIELD);
1030       }
1031       break;
1032     case G_IR_NODE_UNION:
1033       {
1034         GIrNodeUnion *union_;
1035         
1036         union_ = (GIrNodeUnion *)ctx->current_node;
1037         union_->members = g_list_append (union_->members, field);
1038         if (branch)
1039           {
1040             GIrNodeConstant *constant;
1041             
1042             constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1043             ((GIrNode *)constant)->name = g_strdup (name);
1044             constant->value = g_strdup (branch);          
1045             constant->type = union_->discriminator_type;
1046             constant->deprecated = FALSE;
1047             
1048             union_->discriminators = g_list_append (union_->discriminators, constant);
1049           }
1050         state_switch (ctx, STATE_UNION_FIELD);
1051       }
1052       break;
1053     default:
1054       g_assert_not_reached ();
1055     }
1056   
1057   return TRUE;
1058 }
1059
1060 static gboolean
1061 start_alias (GMarkupParseContext *context,
1062              const gchar         *element_name,
1063              const gchar        **attribute_names,
1064              const gchar        **attribute_values,
1065              ParseContext        *ctx,
1066              GError             **error)
1067 {
1068   const gchar *name;
1069   const gchar *target;
1070   char *key;
1071   char *value;
1072
1073   name = find_attribute ("name", attribute_names, attribute_values);
1074   if (name == NULL)
1075     {
1076       MISSING_ATTRIBUTE (context, error, element_name, "name");
1077       return FALSE;
1078     }
1079
1080   target = find_attribute ("target", attribute_names, attribute_values);
1081   if (name == NULL)
1082     {
1083       MISSING_ATTRIBUTE (context, error, element_name, "target");
1084       return FALSE;
1085     }
1086
1087   value = g_strdup (target);
1088   key = g_strdup_printf ("%s.%s", ctx->namespace, name);
1089   if (!strchr (target, '.'))
1090     {
1091       const BasicTypeInfo *basic = parse_basic (target);
1092       if (!basic)
1093         {
1094           g_free (value);
1095           /* For non-basic types, re-qualify the interface */
1096           value = g_strdup_printf ("%s.%s", ctx->namespace, target);
1097         }
1098     }
1099   g_hash_table_replace (ctx->aliases, key, value);
1100
1101   return TRUE;
1102 }
1103
1104 static gboolean
1105 start_enum (GMarkupParseContext *context,
1106              const gchar         *element_name,
1107              const gchar        **attribute_names,
1108              const gchar        **attribute_values,
1109              ParseContext        *ctx,
1110              GError             **error)
1111 {
1112   if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
1113       (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
1114     {
1115       const gchar *name;
1116       const gchar *typename;
1117       const gchar *typeinit;
1118       const gchar *deprecated;
1119       
1120       name = find_attribute ("name", attribute_names, attribute_values);
1121       typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1122       typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1123       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1124       
1125       if (name == NULL)
1126         MISSING_ATTRIBUTE (context, error, element_name, "name");
1127       else 
1128         {             
1129           GIrNodeEnum *enum_;
1130           
1131           if (strcmp (element_name, "enumeration") == 0)
1132             enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
1133           else
1134             enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
1135           ((GIrNode *)enum_)->name = g_strdup (name);
1136           enum_->gtype_name = g_strdup (typename);
1137           enum_->gtype_init = g_strdup (typeinit);
1138           if (deprecated)
1139             enum_->deprecated = TRUE;
1140           else
1141             enum_->deprecated = FALSE;
1142
1143           ctx->current_node = (GIrNode *) enum_;
1144           ctx->current_module->entries = 
1145             g_list_append (ctx->current_module->entries, enum_);              
1146           
1147           state_switch (ctx, STATE_ENUM);
1148         }
1149       
1150       return TRUE;
1151     }
1152   return FALSE;
1153 }
1154
1155 static gboolean
1156 start_property (GMarkupParseContext *context,
1157                 const gchar         *element_name,
1158                 const gchar        **attribute_names,
1159                 const gchar        **attribute_values,
1160                 ParseContext        *ctx,
1161                 GError             **error)
1162 {
1163   if (strcmp (element_name, "property") == 0 &&
1164       (ctx->state == STATE_CLASS ||
1165        ctx->state == STATE_INTERFACE))
1166     {
1167       const gchar *name;
1168       const gchar *readable;
1169       const gchar *writable;
1170       const gchar *construct;
1171       const gchar *construct_only;
1172       
1173       name = find_attribute ("name", attribute_names, attribute_values);
1174       readable = find_attribute ("readable", attribute_names, attribute_values);
1175       writable = find_attribute ("writable", attribute_names, attribute_values);
1176       construct = find_attribute ("construct", attribute_names, attribute_values);
1177       construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1178       
1179       if (name == NULL)
1180         MISSING_ATTRIBUTE (context, error, element_name, "name");
1181       else 
1182         {             
1183           GIrNodeProperty *property;
1184           GIrNodeInterface *iface;
1185           
1186           property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
1187           ctx->current_typed = (GIrNode*) property;
1188
1189           ((GIrNode *)property)->name = g_strdup (name);
1190           
1191           /* Assume properties are readable */
1192           if (readable == NULL || strcmp (readable, "1") == 0)
1193             property->readable = TRUE;
1194           else
1195             property->readable = FALSE;
1196           if (writable && strcmp (writable, "1") == 0)
1197             property->writable = TRUE;
1198           else
1199             property->writable = FALSE;
1200           if (construct && strcmp (construct, "1") == 0)
1201             property->construct = TRUE;
1202           else
1203             property->construct = FALSE;
1204           if (construct_only && strcmp (construct_only, "1") == 0)
1205             property->construct_only = TRUE;
1206           else
1207             property->construct_only = FALSE;
1208
1209           iface = (GIrNodeInterface *)ctx->current_node;
1210           iface->members = g_list_append (iface->members, property);
1211
1212           if (ctx->state == STATE_CLASS)
1213             state_switch (ctx, STATE_CLASS_PROPERTY);
1214           else if (ctx->state == STATE_INTERFACE)
1215             state_switch (ctx, STATE_INTERFACE_PROPERTY);
1216           else
1217             g_assert_not_reached ();
1218         }
1219       
1220       return TRUE;
1221     }
1222   return FALSE;
1223 }
1224
1225 static gint
1226 parse_value (const gchar *str)
1227 {
1228   gchar *shift_op;
1229  
1230   /* FIXME just a quick hack */
1231   shift_op = strstr (str, "<<");
1232
1233   if (shift_op)
1234     {
1235       gint base, shift;
1236
1237       base = strtol (str, NULL, 10);
1238       shift = strtol (shift_op + 3, NULL, 10);
1239       
1240       return base << shift;
1241     }
1242   else
1243     return strtol (str, NULL, 10);
1244
1245   return 0;
1246 }
1247
1248 static gboolean
1249 start_member (GMarkupParseContext *context,
1250               const gchar         *element_name,
1251               const gchar        **attribute_names,
1252               const gchar        **attribute_values,
1253               ParseContext        *ctx,
1254               GError             **error)
1255 {
1256   if (strcmp (element_name, "member") == 0 &&
1257       ctx->state == STATE_ENUM)
1258     {
1259       const gchar *name;
1260       const gchar *value;
1261       const gchar *deprecated;
1262       
1263       name = find_attribute ("name", attribute_names, attribute_values);
1264       value = find_attribute ("value", attribute_names, attribute_values);
1265       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1266       
1267       if (name == NULL)
1268         MISSING_ATTRIBUTE (context, error, element_name, "name");
1269       else 
1270         {             
1271           GIrNodeEnum *enum_;
1272           GIrNodeValue *value_;
1273
1274           value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
1275
1276           ((GIrNode *)value_)->name = g_strdup (name);
1277           
1278           value_->value = parse_value (value);
1279           
1280           if (deprecated)
1281             value_->deprecated = TRUE;
1282           else
1283             value_->deprecated = FALSE;
1284
1285           enum_ = (GIrNodeEnum *)ctx->current_node;
1286           enum_->values = g_list_append (enum_->values, value_);
1287         }
1288       
1289       return TRUE;
1290     }
1291   return FALSE;
1292 }
1293
1294 static gboolean
1295 start_constant (GMarkupParseContext *context,
1296                 const gchar         *element_name,
1297                 const gchar        **attribute_names,
1298                 const gchar        **attribute_values,
1299                 ParseContext        *ctx,
1300                 GError             **error)
1301 {
1302   if (strcmp (element_name, "constant") == 0 &&
1303       (ctx->state == STATE_NAMESPACE ||
1304        ctx->state == STATE_CLASS ||
1305        ctx->state == STATE_INTERFACE))
1306     {
1307       const gchar *name;
1308       const gchar *value;
1309       const gchar *deprecated;
1310       
1311       name = find_attribute ("name", attribute_names, attribute_values);
1312       value = find_attribute ("value", attribute_names, attribute_values);
1313       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1314       
1315       if (name == NULL)
1316         MISSING_ATTRIBUTE (context, error, element_name, "name");
1317       else if (value == NULL)
1318         MISSING_ATTRIBUTE (context, error, element_name, "value");
1319       else 
1320         {             
1321           GIrNodeConstant *constant;
1322
1323           constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1324
1325           ((GIrNode *)constant)->name = g_strdup (name);
1326           constant->value = g_strdup (value);
1327
1328           ctx->current_typed = (GIrNode*) constant;
1329
1330           if (deprecated)
1331             constant->deprecated = TRUE;
1332           else
1333             constant->deprecated = FALSE;
1334
1335           if (ctx->state == STATE_NAMESPACE)
1336             {
1337               ctx->current_node = (GIrNode *) constant;
1338               ctx->current_module->entries = 
1339                 g_list_append (ctx->current_module->entries, constant);
1340             }
1341           else
1342             {
1343               GIrNodeInterface *iface;
1344
1345               iface = (GIrNodeInterface *)ctx->current_node;
1346               iface->members = g_list_append (iface->members, constant);
1347             }
1348
1349           switch (ctx->state)
1350             {
1351             case STATE_NAMESPACE:
1352               state_switch (ctx, STATE_NAMESPACE_CONSTANT);
1353               break;
1354             case STATE_CLASS:
1355               state_switch (ctx, STATE_CLASS_CONSTANT);
1356               break;
1357             case STATE_INTERFACE:
1358               state_switch (ctx, STATE_INTERFACE_CONSTANT);
1359               break;
1360             default:
1361               g_assert_not_reached ();
1362               break;
1363             }
1364         }
1365       
1366       return TRUE;
1367     }
1368   return FALSE;
1369 }
1370
1371 static gboolean
1372 start_errordomain (GMarkupParseContext *context,
1373                    const gchar         *element_name,
1374                    const gchar        **attribute_names,
1375                    const gchar        **attribute_values,
1376                    ParseContext        *ctx,
1377                    GError             **error)
1378 {
1379   if (strcmp (element_name, "errordomain") == 0 &&
1380       ctx->state == STATE_NAMESPACE)
1381     {
1382       const gchar *name;
1383       const gchar *getquark;
1384       const gchar *codes;
1385       const gchar *deprecated;
1386       
1387       name = find_attribute ("name", attribute_names, attribute_values);
1388       getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1389       codes = find_attribute ("codes", attribute_names, attribute_values);
1390       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1391       
1392       if (name == NULL)
1393         MISSING_ATTRIBUTE (context, error, element_name, "name");
1394       else if (getquark == NULL)
1395         MISSING_ATTRIBUTE (context, error, element_name, "getquark");
1396       else if (codes == NULL)
1397         MISSING_ATTRIBUTE (context, error, element_name, "codes");
1398       else 
1399         {             
1400           GIrNodeErrorDomain *domain;
1401
1402           domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
1403
1404           ((GIrNode *)domain)->name = g_strdup (name);
1405           domain->getquark = g_strdup (getquark);
1406           domain->codes = g_strdup (codes);
1407
1408           if (deprecated)
1409             domain->deprecated = TRUE;
1410           else
1411             domain->deprecated = FALSE;
1412
1413           ctx->current_node = (GIrNode *) domain;
1414           ctx->current_module->entries = 
1415             g_list_append (ctx->current_module->entries, domain);
1416
1417           state_switch (ctx, STATE_ERRORDOMAIN);
1418         }
1419       
1420       return TRUE;
1421     }
1422   return FALSE;
1423 }
1424
1425 static gboolean
1426 start_interface (GMarkupParseContext *context,
1427                  const gchar         *element_name,
1428                  const gchar        **attribute_names,
1429                  const gchar        **attribute_values,
1430                  ParseContext        *ctx,
1431                  GError             **error)
1432 {
1433   if (strcmp (element_name, "interface") == 0 &&
1434       ctx->state == STATE_NAMESPACE)
1435     {
1436       const gchar *name;
1437       const gchar *typename;
1438       const gchar *typeinit;
1439       const gchar *deprecated;
1440       
1441       name = find_attribute ("name", attribute_names, attribute_values);
1442       typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1443       typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1444       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1445       
1446       if (name == NULL)
1447         MISSING_ATTRIBUTE (context, error, element_name, "name");
1448       else if (typename == NULL)
1449         MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1450       else if (typeinit == NULL)
1451         MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1452       else
1453         {
1454           GIrNodeInterface *iface;
1455
1456           iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
1457           ((GIrNode *)iface)->name = g_strdup (name);
1458           iface->gtype_name = g_strdup (typename);
1459           iface->gtype_init = g_strdup (typeinit);
1460           if (deprecated)
1461             iface->deprecated = TRUE;
1462           else
1463             iface->deprecated = FALSE;
1464           
1465           ctx->current_node = (GIrNode *) iface;
1466           ctx->current_module->entries = 
1467             g_list_append (ctx->current_module->entries, iface);              
1468           
1469           state_switch (ctx, STATE_INTERFACE);
1470           
1471         }
1472       
1473       return TRUE;
1474     }
1475   return FALSE;
1476 }
1477
1478 static gboolean
1479 start_class (GMarkupParseContext *context,
1480               const gchar         *element_name,
1481               const gchar        **attribute_names,
1482               const gchar        **attribute_values,
1483               ParseContext        *ctx,
1484               GError             **error)
1485 {
1486   if (strcmp (element_name, "class") == 0 &&
1487       ctx->state == STATE_NAMESPACE)
1488     {
1489       const gchar *name;
1490       const gchar *parent;
1491       const gchar *typename;
1492       const gchar *typeinit;
1493       const gchar *deprecated;
1494       const gchar *abstract;
1495       
1496       name = find_attribute ("name", attribute_names, attribute_values);
1497       parent = find_attribute ("parent", attribute_names, attribute_values);
1498       typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1499       typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1500       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1501       abstract = find_attribute ("abstract", attribute_names, attribute_values);
1502       
1503       if (name == NULL)
1504         MISSING_ATTRIBUTE (context, error, element_name, "name");
1505       else if (typename == NULL)
1506         MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1507       else if (typeinit == NULL && strcmp (typename, "GObject"))
1508         MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1509       else
1510         {
1511           GIrNodeInterface *iface;
1512
1513           iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
1514           ((GIrNode *)iface)->name = g_strdup (name);
1515           iface->gtype_name = g_strdup (typename);
1516           iface->gtype_init = g_strdup (typeinit);
1517           iface->parent = g_strdup (parent);
1518           if (deprecated)
1519             iface->deprecated = TRUE;
1520           else
1521             iface->deprecated = FALSE;
1522
1523           iface->abstract = abstract && strcmp (abstract, "1") == 0;
1524
1525           ctx->current_node = (GIrNode *) iface;
1526           ctx->current_module->entries = 
1527             g_list_append (ctx->current_module->entries, iface);              
1528           
1529           state_switch (ctx, STATE_CLASS);
1530         }
1531       
1532       return TRUE;
1533     }
1534   return  FALSE;
1535 }
1536
1537 static gboolean
1538 start_type (GMarkupParseContext *context,
1539             const gchar         *element_name,
1540             const gchar        **attribute_names,
1541             const gchar        **attribute_values,
1542             ParseContext       *ctx,
1543             GError             **error)
1544 {
1545   const gchar *name;
1546   const gchar *ctype;
1547   gboolean is_array;
1548   gboolean is_varargs;
1549   GIrNodeType *typenode;
1550
1551   is_array = strcmp (element_name, "array") == 0;
1552   is_varargs = strcmp (element_name, "varargs") == 0;
1553
1554   if (!(is_array || is_varargs || (strcmp (element_name, "type") == 0)))
1555     return FALSE;
1556
1557   if (ctx->state == STATE_TYPE) 
1558     {
1559       ctx->type_depth++;
1560       ctx->type_stack = g_list_prepend (ctx->type_stack, ctx->type_parameters);
1561       ctx->type_parameters = NULL;
1562     } 
1563   else if (ctx->state == STATE_FUNCTION_PARAMETER ||
1564            ctx->state == STATE_FUNCTION_RETURN || 
1565            ctx->state == STATE_STRUCT_FIELD ||
1566            ctx->state == STATE_UNION_FIELD ||
1567            ctx->state == STATE_CLASS_PROPERTY ||
1568            ctx->state == STATE_CLASS_FIELD ||
1569            ctx->state == STATE_INTERFACE_FIELD ||
1570            ctx->state == STATE_INTERFACE_PROPERTY ||
1571            ctx->state == STATE_BOXED_FIELD ||
1572            ctx->state == STATE_NAMESPACE_CONSTANT ||
1573            ctx->state == STATE_CLASS_CONSTANT ||
1574            ctx->state == STATE_INTERFACE_CONSTANT
1575            )
1576     {
1577       state_switch (ctx, STATE_TYPE);
1578       ctx->type_depth = 1;
1579       if (is_varargs)
1580         {
1581           switch (ctx->current_node->type)
1582             {
1583             case G_IR_NODE_FUNCTION:
1584             case G_IR_NODE_CALLBACK:
1585               {
1586                 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1587                 func->is_varargs = TRUE;
1588               }
1589               break;
1590             case G_IR_NODE_VFUNC:
1591               {
1592                 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1593                 vfunc->is_varargs = TRUE;
1594               }
1595               break;
1596             /* list others individually rather than with default: so that compiler
1597              * warns if new node types are added without adding them to the switch
1598              */
1599             case G_IR_NODE_INVALID:
1600             case G_IR_NODE_ENUM:
1601             case G_IR_NODE_FLAGS:
1602             case G_IR_NODE_CONSTANT:
1603             case G_IR_NODE_ERROR_DOMAIN:
1604             case G_IR_NODE_PARAM:
1605             case G_IR_NODE_TYPE:
1606             case G_IR_NODE_PROPERTY:
1607             case G_IR_NODE_SIGNAL:
1608             case G_IR_NODE_VALUE:
1609             case G_IR_NODE_FIELD:
1610             case G_IR_NODE_XREF:
1611             case G_IR_NODE_STRUCT:
1612             case G_IR_NODE_BOXED:
1613             case G_IR_NODE_OBJECT:
1614             case G_IR_NODE_INTERFACE:
1615             case G_IR_NODE_UNION:
1616               g_assert_not_reached ();
1617               break;
1618             }
1619         }
1620       ctx->type_stack = NULL;
1621       ctx->type_parameters = NULL;
1622     }
1623
1624   if (!ctx->current_typed)
1625     {
1626       g_set_error (error,
1627                    G_MARKUP_ERROR,
1628                    G_MARKUP_ERROR_INVALID_CONTENT,
1629                    "The element <type> is invalid here");
1630       return FALSE;
1631     }
1632
1633   if (is_varargs)
1634     return TRUE;
1635
1636   if (is_array) 
1637     {
1638       const char *zero;
1639       const char *len;
1640       const char *size;
1641
1642       typenode = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
1643
1644       typenode->tag = GI_TYPE_TAG_ARRAY;
1645       typenode->is_pointer = TRUE;
1646       typenode->is_array = TRUE;
1647       
1648       zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
1649       len = find_attribute ("length", attribute_names, attribute_values);
1650       size = find_attribute ("fixed-size", attribute_names, attribute_values);
1651       
1652       typenode->zero_terminated = !(zero && strcmp (zero, "1") != 0);
1653       typenode->has_length = len != NULL;
1654       typenode->length = typenode->has_length ? atoi (len) : -1;
1655       
1656       typenode->has_size = size != NULL;
1657       typenode->size = typenode->has_size ? atoi (size) : -1;
1658     }
1659   else
1660     {
1661       int pointer_depth;
1662       name = find_attribute ("name", attribute_names, attribute_values);
1663
1664       if (name == NULL)
1665         MISSING_ATTRIBUTE (context, error, element_name, "name");
1666       
1667       pointer_depth = 0;
1668       ctype = find_attribute ("c:type", attribute_names, attribute_values);
1669       if (ctype != NULL)
1670         {
1671           const char *cp = ctype + strlen(ctype) - 1;
1672           while (cp > ctype && *cp-- == '*')
1673             pointer_depth++;
1674         }
1675       
1676       if (ctx->current_typed->type == G_IR_NODE_PARAM &&
1677           ((GIrNodeParam *)ctx->current_typed)->out &&
1678           pointer_depth > 0)
1679         pointer_depth--;
1680       
1681       typenode = parse_type (ctx, name);
1682
1683       /* A 'disguised' structure is one where the c:type is a typedef that
1684        * doesn't look like a pointer, but is internally.
1685        */
1686       if (typenode->tag == GI_TYPE_TAG_INTERFACE &&
1687           is_disguised_structure (ctx, typenode->interface))
1688         pointer_depth++;
1689
1690       if (pointer_depth > 0)
1691         typenode->is_pointer = TRUE;
1692     }
1693
1694   ctx->type_parameters = g_list_append (ctx->type_parameters, typenode);
1695   
1696   return TRUE;
1697 }
1698
1699 static void
1700 end_type_top (ParseContext *ctx)
1701 {
1702   GIrNodeType *typenode;
1703
1704   if (!ctx->type_parameters)
1705     goto out;
1706
1707   typenode = (GIrNodeType*)ctx->type_parameters->data;
1708
1709   /* Default to pointer for unspecified containers */
1710   if (typenode->tag == GI_TYPE_TAG_ARRAY ||
1711       typenode->tag == GI_TYPE_TAG_GLIST ||
1712       typenode->tag == GI_TYPE_TAG_GSLIST)
1713     {
1714       if (typenode->parameter_type1 == NULL)
1715         typenode->parameter_type1 = parse_type (ctx, "any");
1716     }
1717   else if (typenode->tag == GI_TYPE_TAG_GHASH)
1718     {
1719       if (typenode->parameter_type1 == NULL)
1720         {
1721           typenode->parameter_type1 = parse_type (ctx, "any");
1722           typenode->parameter_type2 = parse_type (ctx, "any");
1723         }
1724     }
1725
1726   switch (ctx->current_typed->type)
1727     {
1728     case G_IR_NODE_PARAM:
1729       {
1730         GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
1731         param->type = typenode;
1732       }
1733       break;
1734     case G_IR_NODE_FIELD:
1735       {
1736         GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
1737         field->type = typenode;
1738       }
1739       break;
1740     case G_IR_NODE_PROPERTY:
1741       {
1742         GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
1743         property->type = typenode;
1744       }
1745       break;
1746     case G_IR_NODE_CONSTANT:
1747       {
1748         GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
1749         constant->type = typenode;
1750       }
1751       break;
1752     default:
1753       g_printerr("current node is %d\n", ctx->current_node->type);
1754       g_assert_not_reached ();
1755     }
1756   g_list_free (ctx->type_parameters);
1757
1758  out:  
1759   ctx->type_depth = 0;
1760   ctx->type_parameters = NULL;
1761   ctx->current_typed = NULL;
1762 }
1763
1764 static void
1765 end_type_recurse (ParseContext *ctx)
1766 {
1767   GIrNodeType *parent;
1768   GIrNodeType *param = NULL;
1769
1770   parent = (GIrNodeType *) ((GList*)ctx->type_stack->data)->data;
1771   if (ctx->type_parameters)
1772     param = (GIrNodeType *) ctx->type_parameters->data;
1773
1774   if (parent->tag == GI_TYPE_TAG_ARRAY ||
1775       parent->tag == GI_TYPE_TAG_GLIST ||
1776       parent->tag == GI_TYPE_TAG_GSLIST)
1777     {
1778       g_assert (param != NULL);
1779
1780       if (parent->parameter_type1 == NULL)
1781         parent->parameter_type1 = param;
1782       else
1783         g_assert_not_reached ();
1784     }
1785   else if (parent->tag == GI_TYPE_TAG_GHASH)
1786     {
1787       g_assert (param != NULL);
1788
1789       if (parent->parameter_type1 == NULL)
1790         parent->parameter_type1 = param;
1791       else if (parent->parameter_type2 == NULL)
1792         parent->parameter_type2 = param;
1793       else
1794         g_assert_not_reached ();
1795     }
1796   g_list_free (ctx->type_parameters);
1797   ctx->type_parameters = (GList *)ctx->type_stack->data;
1798   ctx->type_stack = g_list_delete_link (ctx->type_stack, ctx->type_stack);
1799 }
1800
1801 static void
1802 end_type (ParseContext *ctx)
1803 {
1804   if (ctx->type_depth == 1)
1805     {
1806       end_type_top (ctx);
1807       state_switch (ctx, ctx->prev_state);
1808     }
1809   else
1810     {
1811       end_type_recurse (ctx);
1812       ctx->type_depth--;
1813     }
1814 }
1815
1816 static gboolean
1817 start_return_value (GMarkupParseContext *context,
1818                     const gchar         *element_name,
1819                     const gchar        **attribute_names,
1820                     const gchar        **attribute_values,
1821                     ParseContext       *ctx,
1822                     GError             **error)
1823 {
1824   if (strcmp (element_name, "return-value") == 0 &&
1825       ctx->state == STATE_FUNCTION)
1826     {
1827       GIrNodeParam *param;
1828       const gchar  *transfer;
1829
1830       param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
1831       param->in = FALSE;
1832       param->out = FALSE;
1833       param->retval = TRUE;
1834
1835       ctx->current_typed = (GIrNode*) param;
1836
1837       state_switch (ctx, STATE_FUNCTION_RETURN);
1838
1839       transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
1840       parse_param_transfer (param, transfer);
1841
1842       switch (ctx->current_node->type)
1843         {
1844         case G_IR_NODE_FUNCTION:
1845         case G_IR_NODE_CALLBACK:
1846           {
1847             GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1848             func->result = param;
1849           }
1850           break;
1851         case G_IR_NODE_SIGNAL:
1852           {
1853             GIrNodeSignal *signal = (GIrNodeSignal *)ctx->current_node;
1854             signal->result = param;
1855           }
1856           break;
1857         case G_IR_NODE_VFUNC:
1858           {
1859             GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1860             vfunc->result = param;
1861           }
1862           break;
1863         default:
1864           g_assert_not_reached ();
1865         }
1866       
1867       return TRUE;
1868     }
1869
1870   return FALSE;
1871 }
1872
1873 static gboolean
1874 start_implements (GMarkupParseContext *context,
1875                   const gchar         *element_name,
1876                   const gchar        **attribute_names,
1877                   const gchar        **attribute_values,
1878                   ParseContext       *ctx,
1879                   GError             **error)
1880 {
1881   GIrNodeInterface *iface;
1882   const char *name;
1883
1884   if (strcmp (element_name, "implements") != 0 ||
1885       !(ctx->state == STATE_CLASS))
1886     return FALSE;
1887
1888   state_switch (ctx, STATE_IMPLEMENTS);
1889   
1890   name = find_attribute ("name", attribute_names, attribute_values);
1891   if (name == NULL)
1892     {
1893       MISSING_ATTRIBUTE (context, error, element_name, "name");
1894       return FALSE;
1895     }
1896       
1897   iface = (GIrNodeInterface *)ctx->current_node;
1898   iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
1899
1900   return TRUE;
1901 }
1902
1903 static gboolean
1904 start_glib_signal (GMarkupParseContext *context,
1905                    const gchar         *element_name,
1906                    const gchar        **attribute_names,
1907                    const gchar        **attribute_values,
1908                    ParseContext       *ctx,
1909                    GError             **error)
1910 {
1911   if (strcmp (element_name, "glib:signal") == 0 && 
1912       (ctx->state == STATE_CLASS ||
1913        ctx->state == STATE_INTERFACE))
1914     {
1915       const gchar *name;
1916       const gchar *when;
1917       const gchar *no_recurse;
1918       const gchar *detailed;
1919       const gchar *action;
1920       const gchar *no_hooks;
1921       const gchar *has_class_closure;
1922       
1923       name = find_attribute ("name", attribute_names, attribute_values);
1924       when = find_attribute ("when", attribute_names, attribute_values);
1925       no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
1926       detailed = find_attribute ("detailed", attribute_names, attribute_values);
1927       action = find_attribute ("action", attribute_names, attribute_values);
1928       no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
1929       has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
1930       
1931       if (name == NULL)
1932         MISSING_ATTRIBUTE (context, error, element_name, "name");
1933       else
1934         {
1935           GIrNodeInterface *iface;
1936           GIrNodeSignal *signal;
1937
1938           signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
1939           
1940           ((GIrNode *)signal)->name = g_strdup (name);
1941           
1942           signal->run_first = FALSE;
1943           signal->run_last = FALSE;
1944           signal->run_cleanup = FALSE;
1945           if (when == NULL || strcmp (when, "LAST") == 0)
1946             signal->run_last = TRUE;
1947           else if (strcmp (when, "FIRST") == 0)
1948             signal->run_first = TRUE;
1949           else 
1950             signal->run_cleanup = TRUE;
1951           
1952           if (no_recurse && strcmp (no_recurse, "1") == 0)
1953             signal->no_recurse = TRUE;
1954           else
1955             signal->no_recurse = FALSE;
1956           if (detailed && strcmp (detailed, "1") == 0)
1957             signal->detailed = TRUE;
1958           else
1959             signal->detailed = FALSE;
1960           if (action && strcmp (action, "1") == 0)
1961             signal->action = TRUE;
1962           else
1963             signal->action = FALSE;
1964           if (no_hooks && strcmp (no_hooks, "1") == 0)
1965             signal->no_hooks = TRUE;
1966           else
1967             signal->no_hooks = FALSE;
1968           if (has_class_closure && strcmp (has_class_closure, "1") == 0)
1969             signal->has_class_closure = TRUE;
1970           else
1971             signal->has_class_closure = FALSE;
1972
1973           iface = (GIrNodeInterface *)ctx->current_node;
1974           iface->members = g_list_append (iface->members, signal);
1975
1976           ctx->current_node = (GIrNode *)signal;
1977           state_switch (ctx, STATE_FUNCTION);
1978         }
1979       
1980       return TRUE;
1981     }
1982   return FALSE;
1983 }
1984
1985 static gboolean
1986 start_vfunc (GMarkupParseContext *context,
1987              const gchar         *element_name,
1988              const gchar        **attribute_names,
1989              const gchar        **attribute_values,
1990              ParseContext       *ctx,
1991              GError             **error)
1992 {
1993   if (strcmp (element_name, "vfunc") == 0 && 
1994       (ctx->state == STATE_CLASS ||
1995        ctx->state == STATE_INTERFACE))
1996     {
1997       const gchar *name;
1998       const gchar *must_chain_up;
1999       const gchar *override;
2000       const gchar *is_class_closure;
2001       const gchar *offset;
2002       
2003       name = find_attribute ("name", attribute_names, attribute_values);
2004       must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);        
2005       override = find_attribute ("override", attribute_names, attribute_values);
2006       is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
2007       offset = find_attribute ("offset", attribute_names, attribute_values);
2008       
2009       if (name == NULL)
2010         MISSING_ATTRIBUTE (context, error, element_name, "name");
2011       else
2012         {
2013           GIrNodeInterface *iface;
2014           GIrNodeVFunc *vfunc;
2015
2016           vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
2017           
2018           ((GIrNode *)vfunc)->name = g_strdup (name);
2019
2020           if (must_chain_up && strcmp (must_chain_up, "1") == 0)
2021             vfunc->must_chain_up = TRUE;
2022           else
2023             vfunc->must_chain_up = FALSE;
2024
2025           if (override && strcmp (override, "always") == 0)
2026             {
2027               vfunc->must_be_implemented = TRUE;
2028               vfunc->must_not_be_implemented = FALSE;
2029             }
2030           else if (override && strcmp (override, "never") == 0)
2031             {
2032               vfunc->must_be_implemented = FALSE;
2033               vfunc->must_not_be_implemented = TRUE;
2034             }
2035           else
2036             {
2037               vfunc->must_be_implemented = FALSE;
2038               vfunc->must_not_be_implemented = FALSE;
2039             }
2040           
2041           if (is_class_closure && strcmp (is_class_closure, "1") == 0)
2042             vfunc->is_class_closure = TRUE;
2043           else
2044             vfunc->is_class_closure = FALSE;
2045           
2046           if (offset)
2047             vfunc->offset = atoi (offset);
2048           else
2049             vfunc->offset = 0;
2050
2051           iface = (GIrNodeInterface *)ctx->current_node;
2052           iface->members = g_list_append (iface->members, vfunc);
2053
2054           ctx->current_node = (GIrNode *)vfunc;
2055           state_switch (ctx, STATE_FUNCTION);
2056         }
2057       
2058       return TRUE;
2059     }
2060   return FALSE;
2061 }
2062
2063
2064 static gboolean
2065 start_struct (GMarkupParseContext *context,
2066               const gchar         *element_name,
2067               const gchar        **attribute_names,
2068               const gchar        **attribute_values,
2069               ParseContext       *ctx,
2070               GError             **error)
2071 {
2072   if (strcmp (element_name, "record") == 0 && 
2073       ctx->state == STATE_NAMESPACE)
2074     {
2075       const gchar *name;
2076       const gchar *deprecated;
2077       const gchar *disguised;
2078       const gchar *gtype_name;
2079       const gchar *gtype_init;
2080       GIrNodeStruct *struct_;
2081       
2082       name = find_attribute ("name", attribute_names, attribute_values);
2083       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
2084       disguised = find_attribute ("disguised", attribute_names, attribute_values);
2085       gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values);
2086       gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values);
2087
2088       if (name == NULL)
2089         {
2090           MISSING_ATTRIBUTE (context, error, element_name, "name");
2091           return FALSE;
2092         }
2093       if ((gtype_name == NULL && gtype_init != NULL))
2094         {
2095           MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
2096           return FALSE;
2097         }
2098       if ((gtype_name != NULL && gtype_init == NULL))
2099         {
2100           MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
2101           return FALSE;
2102         }
2103
2104       struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
2105       
2106       ((GIrNode *)struct_)->name = g_strdup (name);
2107       if (deprecated)
2108         struct_->deprecated = TRUE;
2109       else
2110         struct_->deprecated = FALSE;
2111
2112       if (disguised && strcmp (disguised, "1") == 0)
2113         struct_->disguised = TRUE;
2114
2115       struct_->gtype_name = g_strdup (gtype_name);
2116       struct_->gtype_init = g_strdup (gtype_init);
2117       
2118       ctx->current_node = (GIrNode *)struct_;
2119       ctx->current_module->entries = 
2120         g_list_append (ctx->current_module->entries, struct_);
2121       
2122       state_switch (ctx, STATE_STRUCT);
2123       return TRUE;
2124     }
2125   return FALSE;
2126 }
2127   
2128
2129 static gboolean
2130 start_union (GMarkupParseContext *context,
2131              const gchar         *element_name,
2132              const gchar        **attribute_names,
2133              const gchar        **attribute_values,
2134              ParseContext       *ctx,
2135              GError             **error)
2136 {
2137   if (strcmp (element_name, "union") == 0 && 
2138       ctx->state == STATE_NAMESPACE)
2139     {
2140       const gchar *name;
2141       const gchar *deprecated;
2142       const gchar *typename;
2143       const gchar *typeinit;
2144       
2145       name = find_attribute ("name", attribute_names, attribute_values);
2146       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
2147       typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
2148       typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
2149       
2150       if (name == NULL)
2151         MISSING_ATTRIBUTE (context, error, element_name, "name");
2152       else
2153         {
2154           GIrNodeUnion *union_;
2155
2156           union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
2157           
2158           ((GIrNode *)union_)->name = g_strdup (name);
2159           union_->gtype_name = g_strdup (typename);
2160           union_->gtype_init = g_strdup (typeinit);
2161           if (deprecated)
2162             union_->deprecated = TRUE;
2163           else
2164             union_->deprecated = FALSE;
2165
2166           ctx->current_node = (GIrNode *)union_;
2167           ctx->current_module->entries = 
2168             g_list_append (ctx->current_module->entries, union_);
2169           
2170           state_switch (ctx, STATE_UNION);
2171         }
2172       return TRUE;
2173     }
2174   return FALSE;
2175 }
2176
2177 static gboolean
2178 start_discriminator (GMarkupParseContext *context,
2179                      const gchar         *element_name,
2180                      const gchar        **attribute_names,
2181                      const gchar        **attribute_values,
2182                      ParseContext       *ctx,
2183                      GError             **error)
2184 {
2185   if (strcmp (element_name, "discriminator") == 0 &&
2186       ctx->state == STATE_UNION)
2187     {
2188       const gchar *type;
2189       const gchar *offset;
2190       
2191       type = find_attribute ("type", attribute_names, attribute_values);
2192       offset = find_attribute ("offset", attribute_names, attribute_values);
2193       if (type == NULL)
2194         MISSING_ATTRIBUTE (context, error, element_name, "type");
2195       else if (offset == NULL)
2196         MISSING_ATTRIBUTE (context, error, element_name, "offset");
2197         {
2198           ((GIrNodeUnion *)ctx->current_node)->discriminator_type 
2199             = parse_type (ctx, type);
2200           ((GIrNodeUnion *)ctx->current_node)->discriminator_offset 
2201             = atoi (offset);
2202         }
2203       
2204       return TRUE;
2205     }
2206
2207   return FALSE;
2208 }
2209
2210 static gboolean
2211 parse_include (GMarkupParseContext *context,
2212                ParseContext        *ctx,
2213                const char          *name,
2214                const char          *version,
2215                GError             **error)
2216 {
2217   gchar *buffer;
2218   gsize length;
2219   char *girpath;
2220   gboolean success = FALSE;
2221   GList *modules;
2222   GList *l;
2223
2224   for (l = ctx->parser->parsed_modules; l; l = l->next)
2225     {
2226       GIrModule *m = l->data;
2227
2228       if (strcmp (m->name, name) == 0)
2229         {
2230           if (strcmp (m->version, version) == 0)
2231             {
2232               ctx->include_modules = g_list_prepend (ctx->include_modules, m);
2233
2234               return TRUE;
2235             }
2236           else
2237             {
2238               g_set_error (error,
2239                            G_MARKUP_ERROR,
2240                            G_MARKUP_ERROR_INVALID_CONTENT,
2241                            "Module '%s' imported with conflicting versions '%s' and '%s'",
2242                            name, m->version, version);
2243               return FALSE;
2244             }
2245         }
2246     }
2247
2248   girpath = locate_gir (ctx->parser, name, version);
2249
2250   if (girpath == NULL)
2251     {
2252       g_set_error (error,
2253                    G_MARKUP_ERROR,
2254                    G_MARKUP_ERROR_INVALID_CONTENT,
2255                    "Could not find GIR file '%s.gir'; check XDG_DATA_DIRS or use --includedir",
2256                    name);
2257       return FALSE;
2258     }
2259
2260   g_debug ("Parsing include %s", girpath);
2261
2262   if (!g_file_get_contents (girpath, &buffer, &length, error))
2263     {
2264       g_free (girpath);
2265       return FALSE;
2266     }
2267   g_free (girpath);
2268
2269   modules = g_ir_parser_parse_string (ctx->parser, name, buffer, length, error);
2270   success = error != NULL;
2271
2272   ctx->include_modules = g_list_concat (ctx->include_modules,
2273                                         modules);
2274
2275   g_free (buffer);
2276
2277   return success;
2278 }
2279   
2280 extern GLogLevelFlags logged_levels;
2281
2282 static void
2283 start_element_handler (GMarkupParseContext *context,
2284                        const gchar         *element_name,
2285                        const gchar        **attribute_names,
2286                        const gchar        **attribute_values,
2287                        gpointer             user_data,
2288                        GError             **error)
2289 {
2290   ParseContext *ctx = user_data;
2291   gint line_number, char_number;
2292
2293   if (logged_levels & G_LOG_LEVEL_DEBUG)
2294     {
2295       GString *tags = g_string_new ("");
2296       int i;
2297       for (i = 0; attribute_names[i]; i++)
2298         g_string_append_printf (tags, "%s=\"%s\" ",
2299                                 attribute_names[i],
2300                                 attribute_values[i]);
2301
2302       if (i)
2303         {
2304           g_string_insert_c (tags, 0, ' ');
2305           g_string_truncate (tags, tags->len - 1);
2306         }
2307       g_debug ("<%s%s>", element_name, tags->str);
2308       g_string_free (tags, TRUE);
2309     }
2310
2311   switch (element_name[0]) 
2312     {
2313     case 'a':
2314       if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0) 
2315         {
2316           state_switch (ctx, STATE_ALIAS);
2317           goto out;
2318         }
2319       if (start_type (context, element_name,
2320                       attribute_names, attribute_values,
2321                       ctx, error))
2322         goto out;
2323       break;
2324     case 'b':
2325       if (start_enum (context, element_name, 
2326                       attribute_names, attribute_values,
2327                       ctx, error))
2328         goto out;
2329       break;
2330     case 'c':
2331       if (start_function (context, element_name, 
2332                           attribute_names, attribute_values,
2333                           ctx, error))
2334         goto out;
2335       else if (start_constant (context, element_name,
2336                                attribute_names, attribute_values,
2337                                ctx, error))
2338         goto out;
2339       else if (start_class (context, element_name, 
2340                             attribute_names, attribute_values,
2341                             ctx, error))
2342         goto out;
2343       break;
2344
2345     case 'd':
2346       if (start_discriminator (context, element_name, 
2347                                attribute_names, attribute_values,
2348                                ctx, error))
2349         goto out;
2350       break;
2351
2352     case 'e':
2353       if (start_enum (context, element_name, 
2354                       attribute_names, attribute_values,
2355                       ctx, error))
2356         goto out;
2357       else if (start_errordomain (context, element_name, 
2358                       attribute_names, attribute_values,
2359                       ctx, error))
2360         goto out;
2361       break;
2362
2363     case 'f':
2364       if (start_function (context, element_name, 
2365                           attribute_names, attribute_values,
2366                           ctx, error))
2367         goto out;
2368       else if (start_field (context, element_name, 
2369                             attribute_names, attribute_values,
2370                             ctx, error))
2371         goto out;
2372       break;
2373
2374     case 'g':
2375       if (start_glib_boxed (context, element_name,
2376                             attribute_names, attribute_values,
2377                             ctx, error))
2378         goto out;
2379       else if (start_glib_signal (context, element_name,
2380                              attribute_names, attribute_values,
2381                              ctx, error))
2382         goto out;
2383       break;
2384
2385     case 'i':
2386       if (strcmp (element_name, "include") == 0 &&
2387           ctx->state == STATE_REPOSITORY)
2388         {
2389           const gchar *name;
2390           const gchar *version;
2391
2392           name = find_attribute ("name", attribute_names, attribute_values);
2393           version = find_attribute ("version", attribute_names, attribute_values);
2394
2395           if (name == NULL)
2396             {
2397               MISSING_ATTRIBUTE (context, error, element_name, "name");
2398               break;
2399             }
2400           if (version == NULL)
2401             {
2402               MISSING_ATTRIBUTE (context, error, element_name, "version");
2403               break;
2404             }
2405
2406           if (!parse_include (context, ctx, name, version, error))
2407             break;
2408
2409           ctx->dependencies = g_list_prepend (ctx->dependencies,
2410                                               g_strdup_printf ("%s-%s", name, version));
2411
2412
2413           state_switch (ctx, STATE_INCLUDE);
2414           goto out;
2415         }
2416       if (start_interface (context, element_name, 
2417                            attribute_names, attribute_values,
2418                            ctx, error))
2419         goto out;
2420       else if (start_implements (context, element_name,
2421                                  attribute_names, attribute_values,
2422                                  ctx, error))
2423         goto out;
2424       break;
2425
2426     case 'm':
2427       if (start_function (context, element_name, 
2428                           attribute_names, attribute_values,
2429                           ctx, error))
2430         goto out;
2431       else if (start_member (context, element_name, 
2432                           attribute_names, attribute_values,
2433                           ctx, error))
2434         goto out;
2435       break;
2436
2437     case 'n':
2438       if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
2439         {
2440           const gchar *name, *version, *shared_library;
2441
2442           if (ctx->current_module != NULL)
2443             {
2444               g_set_error (error,
2445                            G_MARKUP_ERROR,
2446                            G_MARKUP_ERROR_INVALID_CONTENT,
2447                            "Only one <namespace/> element is currently allowed per <repository/>");
2448               goto out;
2449             }
2450
2451           name = find_attribute ("name", attribute_names, attribute_values);
2452           version = find_attribute ("version", attribute_names, attribute_values);
2453           shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
2454
2455           if (name == NULL)
2456             MISSING_ATTRIBUTE (context, error, element_name, "name");
2457           else if (version == NULL)
2458             MISSING_ATTRIBUTE (context, error, element_name, "version");
2459           else
2460             {
2461               GList *l;
2462
2463               if (strcmp (name, ctx->namespace) != 0)
2464                 g_set_error (error,
2465                              G_MARKUP_ERROR,
2466                              G_MARKUP_ERROR_INVALID_CONTENT,
2467                              "<namespace/> name element '%s' doesn't match file name '%s'",
2468                              name, ctx->namespace);
2469
2470               ctx->current_module = g_ir_module_new (name, version, shared_library);
2471
2472               ctx->current_module->aliases = ctx->aliases;
2473               ctx->aliases = NULL;
2474               ctx->current_module->disguised_structures = ctx->disguised_structures;
2475               ctx->disguised_structures = NULL;
2476
2477               for (l = ctx->include_modules; l; l = l->next)
2478                 g_ir_module_add_include_module (ctx->current_module, l->data);
2479
2480               g_list_free (ctx->include_modules);
2481               ctx->include_modules = NULL;
2482
2483               ctx->modules = g_list_append (ctx->modules, ctx->current_module);
2484               ctx->current_module->dependencies = ctx->dependencies;
2485
2486               state_switch (ctx, STATE_NAMESPACE);
2487               goto out;
2488             }
2489         }
2490       break;
2491
2492     case 'p':
2493       if (start_property (context, element_name,
2494                           attribute_names, attribute_values,
2495                           ctx, error))
2496         goto out;
2497       else if (strcmp (element_name, "parameters") == 0 &&
2498                ctx->state == STATE_FUNCTION)
2499         {
2500           state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2501
2502           goto out;
2503         }
2504       else if (start_parameter (context, element_name,
2505                                 attribute_names, attribute_values,
2506                                 ctx, error))
2507         goto out;
2508       else if (strcmp (element_name, "prerequisite") == 0 &&
2509                ctx->state == STATE_INTERFACE)
2510         {
2511           const gchar *name;
2512
2513           name = find_attribute ("name", attribute_names, attribute_values);
2514
2515           state_switch (ctx, STATE_PREREQUISITE);
2516
2517           if (name == NULL)
2518             MISSING_ATTRIBUTE (context, error, element_name, "name");
2519           else
2520             {  
2521               GIrNodeInterface *iface;
2522
2523               iface = (GIrNodeInterface *)ctx->current_node;
2524               iface->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
2525             }
2526           goto out;
2527         }
2528       break;
2529
2530     case 'r':
2531       if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
2532         {
2533           const gchar *version;
2534
2535           version = find_attribute ("version", attribute_names, attribute_values);
2536           
2537           if (version == NULL)
2538             MISSING_ATTRIBUTE (context, error, element_name, "version");
2539           else if (strcmp (version, "1.0") != 0)
2540             g_set_error (error,
2541                          G_MARKUP_ERROR,
2542                          G_MARKUP_ERROR_INVALID_CONTENT,
2543                          "Unsupported version '%s'",
2544                          version);
2545           else
2546             state_switch (ctx, STATE_REPOSITORY);
2547           
2548           goto out;
2549         }
2550       else if (start_return_value (context, element_name,
2551                                    attribute_names, attribute_values,
2552                                    ctx, error))
2553         goto out;      
2554       else if (start_struct (context, element_name,
2555                              attribute_names, attribute_values,
2556                              ctx, error))
2557         goto out;      
2558       break;
2559
2560     case 'u':
2561       if (start_union (context, element_name,
2562                        attribute_names, attribute_values,
2563                        ctx, error))
2564         goto out;
2565       break;
2566
2567     case 't':
2568       if (start_type (context, element_name,
2569                       attribute_names, attribute_values,
2570                       ctx, error))
2571         goto out;
2572       break;
2573
2574     case 'v':
2575       if (start_vfunc (context, element_name,
2576                        attribute_names, attribute_values,
2577                        ctx, error))
2578         goto out;
2579       if (start_type (context, element_name,
2580                       attribute_names, attribute_values,
2581                       ctx, error))
2582         goto out;
2583       break;
2584     }
2585
2586   g_markup_parse_context_get_position (context, &line_number, &char_number);
2587
2588   if (error && *error == NULL)
2589     g_set_error (error,
2590                  G_MARKUP_ERROR,
2591                  G_MARKUP_ERROR_UNKNOWN_ELEMENT,
2592                  "Unexpected start tag '%s' on line %d char %d; current state=%d",
2593                  element_name,
2594                  line_number, char_number, ctx->state);
2595   
2596  out: ;
2597   if (*error) 
2598     {
2599       g_markup_parse_context_get_position (context, &line_number, &char_number);
2600
2601       fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
2602       backtrace_stderr ();
2603     }
2604 }
2605
2606 static gboolean
2607 require_one_of_end_elements (GMarkupParseContext *context,
2608                              ParseContext        *ctx,
2609                              const char          *actual_name,
2610                              GError             **error, 
2611                              ...)
2612 {
2613   va_list args;
2614   int line_number, char_number;
2615   const char *expected;
2616   gboolean matched = FALSE;
2617
2618   va_start (args, error);
2619
2620   while ((expected = va_arg (args, const char*)) != NULL) 
2621     {
2622       if (strcmp (expected, actual_name) == 0)
2623         {
2624           matched = TRUE;
2625           break;
2626         }
2627     }
2628
2629   va_end (args);
2630
2631   if (matched)
2632     return TRUE;
2633
2634   g_markup_parse_context_get_position (context, &line_number, &char_number);
2635   g_set_error (error,
2636                G_MARKUP_ERROR,
2637                G_MARKUP_ERROR_INVALID_CONTENT,
2638                "Unexpected end tag '%s' on line %d char %d; current state=%d",
2639                actual_name, 
2640                line_number, char_number, ctx->state);
2641   backtrace_stderr();
2642   return FALSE;
2643 }
2644
2645 static gboolean
2646 require_end_element (GMarkupParseContext *context,
2647                      ParseContext        *ctx,
2648                      const char          *expected_name,
2649                      const char          *actual_name,
2650                      GError             **error)
2651 {
2652   return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
2653 }
2654
2655 static void
2656 end_element_handler (GMarkupParseContext *context,
2657                      const gchar         *element_name,
2658                      gpointer             user_data,
2659                      GError             **error)
2660 {
2661   ParseContext *ctx = user_data;
2662
2663   g_debug ("</%s>", element_name);
2664
2665   switch (ctx->state)
2666     {
2667     case STATE_START:
2668     case STATE_END:
2669       /* no need to GError here, GMarkup already catches this */
2670       break;
2671
2672     case STATE_REPOSITORY:
2673       state_switch (ctx, STATE_END);
2674       break;
2675
2676     case STATE_INCLUDE:
2677       if (require_end_element (context, ctx, "include", element_name, error))
2678         {
2679           state_switch (ctx, STATE_REPOSITORY);
2680         }
2681       break;
2682
2683     case STATE_NAMESPACE:
2684       if (require_end_element (context, ctx, "namespace", element_name, error))
2685         {
2686           ctx->current_module = NULL;
2687           state_switch (ctx, STATE_REPOSITORY);
2688         }
2689       break;
2690
2691     case STATE_ALIAS:
2692       if (require_end_element (context, ctx, "alias", element_name, error))
2693         {
2694           state_switch (ctx, STATE_NAMESPACE);
2695         }
2696       break;
2697
2698     case STATE_FUNCTION_RETURN:
2699       if (strcmp ("type", element_name) == 0)
2700         break;
2701       if (require_end_element (context, ctx, "return-value", element_name, error))
2702         {
2703           state_switch (ctx, STATE_FUNCTION);
2704         }
2705       break;
2706
2707     case STATE_FUNCTION_PARAMETERS:
2708       if (require_end_element (context, ctx, "parameters", element_name, error))
2709         {
2710           state_switch (ctx, STATE_FUNCTION);
2711         }
2712       break;
2713
2714     case STATE_FUNCTION_PARAMETER:
2715       if (strcmp ("type", element_name) == 0)
2716         break;
2717       if (require_end_element (context, ctx, "parameter", element_name, error))
2718         {
2719           state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2720         }
2721       break;
2722
2723     case STATE_FUNCTION:
2724       {
2725         gboolean current_is_toplevel;
2726         GList *last = g_list_last (ctx->current_module->entries);
2727         
2728         current_is_toplevel = ctx->current_node == last->data;  
2729
2730         if (current_is_toplevel)
2731           {
2732             ctx->current_node = NULL;
2733             state_switch (ctx, STATE_NAMESPACE);
2734           }
2735         else 
2736           { 
2737             ctx->current_node = g_list_last (ctx->current_module->entries)->data;
2738             if (ctx->current_node->type == G_IR_NODE_INTERFACE)
2739               state_switch (ctx, STATE_INTERFACE);
2740             else if (ctx->current_node->type == G_IR_NODE_OBJECT) 
2741               state_switch (ctx, STATE_CLASS);
2742             else if (ctx->current_node->type == G_IR_NODE_BOXED)
2743               state_switch (ctx, STATE_BOXED);
2744             else if (ctx->current_node->type == G_IR_NODE_STRUCT)
2745               state_switch (ctx, STATE_STRUCT);
2746             else if (ctx->current_node->type == G_IR_NODE_UNION)
2747               state_switch (ctx, STATE_UNION);
2748             else
2749               {
2750                 int line_number, char_number;
2751                 g_markup_parse_context_get_position (context, &line_number, &char_number);
2752                 g_set_error (error,
2753                              G_MARKUP_ERROR,
2754                              G_MARKUP_ERROR_INVALID_CONTENT,
2755                              "Unexpected end tag '%s' on line %d char %d",
2756                              element_name,
2757                              line_number, char_number);
2758               }
2759           }
2760       }
2761       break;
2762
2763     case STATE_CLASS_FIELD:
2764       if (strcmp ("type", element_name) == 0)
2765         break;
2766       if (require_end_element (context, ctx, "field", element_name, error))
2767         {
2768           state_switch (ctx, STATE_CLASS);
2769         }
2770       break;
2771
2772     case STATE_CLASS_PROPERTY:
2773       if (strcmp ("type", element_name) == 0)
2774         break;
2775       if (require_end_element (context, ctx, "property", element_name, error))
2776         {
2777           state_switch (ctx, STATE_CLASS);
2778         }
2779       break;
2780
2781     case STATE_CLASS:
2782       if (require_end_element (context, ctx, "class", element_name, error))
2783         {
2784           ctx->current_node = NULL;
2785           state_switch (ctx, STATE_NAMESPACE);
2786         }
2787       break;
2788
2789     case STATE_ERRORDOMAIN:
2790       if (require_end_element (context, ctx, "errordomain", element_name, error))
2791         {
2792           ctx->current_node = NULL;
2793           state_switch (ctx, STATE_NAMESPACE);
2794         }
2795       break;
2796
2797     case STATE_INTERFACE_PROPERTY:
2798       if (strcmp ("type", element_name) == 0)
2799         break;
2800       if (require_end_element (context, ctx, "property", element_name, error))
2801         {
2802           state_switch (ctx, STATE_INTERFACE);
2803         }
2804       break;
2805
2806     case STATE_INTERFACE_FIELD:
2807       if (strcmp ("type", element_name) == 0)
2808         break;
2809       if (require_end_element (context, ctx, "field", element_name, error))
2810         {
2811           state_switch (ctx, STATE_INTERFACE);
2812         }
2813       break;
2814
2815     case STATE_INTERFACE:
2816       if (require_end_element (context, ctx, "interface", element_name, error))
2817         {
2818           ctx->current_node = NULL;
2819           state_switch (ctx, STATE_NAMESPACE);
2820         }
2821       break;
2822
2823     case STATE_ENUM:
2824       if (strcmp ("member", element_name) == 0)
2825         break;
2826       else if (require_one_of_end_elements (context, ctx, 
2827                                             element_name, error, "enumeration", 
2828                                             "bitfield", NULL))
2829         {
2830           ctx->current_node = NULL;
2831           state_switch (ctx, STATE_NAMESPACE);
2832         }
2833       break;
2834
2835     case STATE_BOXED:
2836       if (require_end_element (context, ctx, "glib:boxed", element_name, error))
2837         {
2838           ctx->current_node = NULL;
2839           state_switch (ctx, STATE_NAMESPACE);
2840         }
2841       break;
2842
2843     case STATE_BOXED_FIELD:
2844       if (strcmp ("type", element_name) == 0)
2845         break;
2846       if (require_end_element (context, ctx, "field", element_name, error))
2847         {
2848           state_switch (ctx, STATE_BOXED);
2849         }
2850       break;
2851
2852     case STATE_STRUCT_FIELD:
2853       if (strcmp ("type", element_name) == 0)
2854         break;
2855       if (require_end_element (context, ctx, "field", element_name, error))
2856         {
2857           state_switch (ctx, STATE_STRUCT);
2858         }
2859       break;
2860
2861     case STATE_STRUCT:
2862       if (require_end_element (context, ctx, "record", element_name, error))
2863         {
2864           ctx->current_node = NULL;
2865           state_switch (ctx, STATE_NAMESPACE);
2866         }
2867       break;
2868
2869     case STATE_UNION_FIELD:
2870       if (strcmp ("type", element_name) == 0)
2871         break;
2872       if (require_end_element (context, ctx, "field", element_name, error))
2873         {
2874           state_switch (ctx, STATE_UNION);
2875         }
2876       break;
2877
2878     case STATE_UNION:
2879       if (require_end_element (context, ctx, "union", element_name, error))
2880         {
2881           ctx->current_node = NULL;
2882           state_switch (ctx, STATE_NAMESPACE);
2883         }
2884       break;
2885     case STATE_IMPLEMENTS:
2886       if (strcmp ("interface", element_name) == 0)
2887         break;
2888       if (require_end_element (context, ctx, "implements", element_name, error))
2889         state_switch (ctx, STATE_CLASS);
2890       break;
2891     case STATE_PREREQUISITE:
2892       if (require_end_element (context, ctx, "prerequisite", element_name, error))
2893         state_switch (ctx, STATE_INTERFACE);
2894       break;
2895     case STATE_NAMESPACE_CONSTANT:
2896     case STATE_CLASS_CONSTANT:
2897     case STATE_INTERFACE_CONSTANT:
2898       if (strcmp ("type", element_name) == 0)
2899         break;
2900       if (require_end_element (context, ctx, "constant", element_name, error))
2901         {
2902           ctx->current_node = NULL;
2903           switch (ctx->state)
2904             {
2905             case STATE_NAMESPACE_CONSTANT:
2906               state_switch (ctx, STATE_NAMESPACE);
2907               break;
2908             case STATE_CLASS_CONSTANT:
2909               state_switch (ctx, STATE_CLASS);
2910               break;
2911             case STATE_INTERFACE_CONSTANT:
2912               state_switch (ctx, STATE_INTERFACE);
2913               break;
2914             default:
2915               g_assert_not_reached ();
2916               break;
2917             }
2918         }
2919       break;
2920     case STATE_TYPE:
2921       if ((strcmp ("type", element_name) == 0) || (strcmp ("array", element_name) == 0) ||
2922           (strcmp ("varargs", element_name) == 0))
2923         {
2924           end_type (ctx);
2925           break;
2926         }
2927     default:
2928       g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
2929     }
2930 }
2931
2932 static void 
2933 text_handler (GMarkupParseContext *context,
2934               const gchar         *text,
2935               gsize                text_len,  
2936               gpointer             user_data,
2937               GError             **error)
2938 {
2939   /* FIXME warn about non-whitespace text */
2940 }
2941
2942 static void
2943 cleanup (GMarkupParseContext *context,
2944          GError              *error,
2945          gpointer             user_data)
2946 {
2947   ParseContext *ctx = user_data;
2948   GList *m;
2949
2950   for (m = ctx->modules; m; m = m->next)
2951     g_ir_module_free (m->data);
2952   g_list_free (ctx->modules);
2953   ctx->modules = NULL;
2954   
2955   ctx->current_module = NULL;
2956 }
2957
2958 static GList *
2959 post_filter_varargs_functions (GList *list)
2960 {
2961   GList *iter;
2962
2963   iter = list;
2964   while (iter)
2965     {
2966       GList *link = iter;
2967       GIrNode *node = iter->data;
2968
2969       iter = iter->next;
2970
2971       if (node->type == G_IR_NODE_FUNCTION)
2972         {
2973           if (((GIrNodeFunction*)node)->is_varargs)
2974             {
2975               list = g_list_delete_link (list, link);
2976             }
2977         }
2978     }
2979   return list;
2980 }
2981
2982 static void
2983 post_filter (GIrModule *module)
2984 {
2985   GList *iter;
2986
2987   module->entries = post_filter_varargs_functions (module->entries);
2988   iter = module->entries;
2989   while (iter)
2990     {
2991       GIrNode *node = iter->data;
2992
2993       iter = iter->next;
2994       
2995       if (node->type == G_IR_NODE_OBJECT || 
2996           node->type == G_IR_NODE_INTERFACE) 
2997         {
2998           GIrNodeInterface *iface = (GIrNodeInterface*)node;
2999           iface->members = post_filter_varargs_functions (iface->members);
3000         }
3001       else if (node->type == G_IR_NODE_BOXED)
3002         {
3003           GIrNodeBoxed *boxed = (GIrNodeBoxed*)node;
3004           boxed->members = post_filter_varargs_functions (boxed->members);
3005         }
3006       else if (node->type == G_IR_NODE_STRUCT)
3007         {
3008           GIrNodeStruct *iface = (GIrNodeStruct*)node;
3009           iface->members = post_filter_varargs_functions (iface->members);
3010         }
3011       else if (node->type == G_IR_NODE_UNION)
3012         {
3013           GIrNodeUnion *iface = (GIrNodeUnion*)node;
3014           iface->members = post_filter_varargs_functions (iface->members);
3015         }
3016     }
3017 }
3018
3019 /**
3020  * g_ir_parser_parse_string:
3021  * @parser: a #GIrParser
3022  * @error: return location for a #GError, or %NULL
3023  *
3024  * Parse a string that holds a complete GIR XML file, and return a list of a
3025  * a #GirModule for each &lt;namespace/&gt; element within the file.
3026  *
3027  * @returns: a newly allocated list of #GIrModule. The modules themselves
3028  *  are owned by the #GIrParser and will be freed along with the parser.
3029  */
3030 GList *
3031 g_ir_parser_parse_string (GIrParser           *parser,
3032                           const gchar         *namespace,
3033                           const gchar         *buffer,
3034                           gssize               length,
3035                           GError             **error)
3036 {
3037   ParseContext ctx = { 0 };
3038   GMarkupParseContext *context;
3039
3040   ctx.parser = parser;
3041   ctx.state = STATE_START;
3042   ctx.namespace = namespace;
3043   ctx.include_modules = NULL;
3044   ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
3045   ctx.disguised_structures = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
3046   ctx.type_depth = 0;
3047   ctx.dependencies = NULL;
3048   ctx.current_module = NULL;
3049
3050   context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
3051
3052   if (!g_markup_parse_context_parse (context, buffer, length, error))
3053     goto out;
3054
3055   if (!g_markup_parse_context_end_parse (context, error))
3056     goto out;
3057
3058   g_markup_parse_context_free (context);
3059   
3060   context = g_markup_parse_context_new (&markup_parser, 0, &ctx, NULL);
3061   if (!g_markup_parse_context_parse (context, buffer, length, error))
3062     goto out;
3063
3064   if (!g_markup_parse_context_end_parse (context, error))
3065     goto out;
3066
3067   parser->parsed_modules = g_list_concat (g_list_copy (ctx.modules),
3068                                           parser->parsed_modules);
3069
3070  out:
3071
3072   if (ctx.modules == NULL)
3073     {
3074       /* An error occurred before we created a module, so we haven't
3075        * transferred ownership of these hash tables to the module.
3076        */
3077       if (ctx.aliases != NULL)
3078         g_hash_table_destroy (ctx.aliases);
3079       if (ctx.disguised_structures != NULL)
3080         g_hash_table_destroy (ctx.disguised_structures);
3081       g_list_free (ctx.include_modules);
3082     }
3083   
3084   g_markup_parse_context_free (context);
3085   
3086   return ctx.modules;
3087 }
3088
3089 /**
3090  * g_ir_parser_parse_file:
3091  * @parser: a #GIrParser
3092  * @error: return location for a #GError, or %NULL
3093  *
3094  * Parse GIR XML file, and return a list of a a #GirModule for each
3095  * &lt;namespace/&gt; element within the file.
3096  *
3097  * @returns: a newly allocated list of #GIrModule. The modules themselves
3098  *  are owned by the #GIrParser and will be freed along with the parser.
3099  */
3100 GList *
3101 g_ir_parser_parse_file (GIrParser   *parser,
3102                         const gchar *filename,
3103                         GError     **error)
3104 {
3105   gchar *buffer;
3106   gsize length;
3107   GList *modules;
3108   GList *iter;
3109   const char *slash;
3110   char *dash;
3111   char *namespace;
3112
3113   if (!g_str_has_suffix (filename, ".gir"))
3114     {
3115       g_set_error (error,
3116                    G_MARKUP_ERROR,
3117                    G_MARKUP_ERROR_INVALID_CONTENT,
3118                    "Expected filename to end with '.gir'");
3119       return NULL;
3120     }
3121
3122   g_debug ("[parsing] filename %s", filename);
3123
3124   slash = g_strrstr (filename, "/");
3125   if (!slash)
3126     namespace = g_strdup (filename);
3127   else
3128     namespace = g_strdup (slash+1);
3129   namespace[strlen(namespace)-4] = '\0';
3130
3131   /* Remove version */
3132   dash = strstr (namespace, "-");
3133   if (dash != NULL)
3134     *dash = '\0';
3135
3136   if (!g_file_get_contents (filename, &buffer, &length, error))
3137     return NULL;
3138   
3139   modules = g_ir_parser_parse_string (parser, namespace, buffer, length, error);
3140
3141   for (iter = modules; iter; iter = iter->next) 
3142     {
3143       post_filter ((GIrModule*)iter->data);
3144     }
3145
3146   g_free (namespace);
3147
3148   g_free (buffer);
3149
3150   return modules;
3151 }
3152
3153