Bug 559706 - interface prequisites
[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     case STATE_BOXED:
678     case STATE_STRUCT:
679     case STATE_UNION:
680       found = strcmp (element_name, "constructor") == 0;
681       /* fallthrough */
682     case STATE_INTERFACE:
683       found = (found ||
684                strcmp (element_name, "method") == 0 ||
685                strcmp (element_name, "callback") == 0);
686       break;
687     default:
688       break;
689     }
690
691   if (!found)
692     return FALSE;
693
694   name = find_attribute ("name", attribute_names, attribute_values);
695   symbol = find_attribute ("c:identifier", attribute_names, attribute_values);
696   deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
697   throws = find_attribute ("throws", attribute_names, attribute_values);
698       
699   if (name == NULL)
700     {
701       MISSING_ATTRIBUTE (context, error, element_name, "name");
702       return FALSE;
703     }
704   else if (strcmp (element_name, "callback") != 0 && symbol == NULL)
705     {
706       MISSING_ATTRIBUTE (context, error, element_name, "c:identifier");
707       return FALSE;
708     }
709
710   function = (GIrNodeFunction *) g_ir_node_new (G_IR_NODE_FUNCTION);
711       
712   ((GIrNode *)function)->name = g_strdup (name);
713   function->symbol = g_strdup (symbol);
714   function->parameters = NULL;
715   if (deprecated)
716     function->deprecated = TRUE;
717   else
718     function->deprecated = FALSE;
719   
720   if (strcmp (element_name, "method") == 0 ||
721       strcmp (element_name, "constructor") == 0)
722     {
723       function->is_method = TRUE;
724       
725       if (strcmp (element_name, "constructor") == 0)
726         function->is_constructor = TRUE;
727       else
728         function->is_constructor = FALSE;
729     }
730   else
731     {
732       function->is_method = FALSE;
733       function->is_setter = FALSE;
734       function->is_getter = FALSE;
735       function->is_constructor = FALSE;
736       if (strcmp (element_name, "callback") == 0)
737         ((GIrNode *)function)->type = G_IR_NODE_CALLBACK;
738     }
739
740   if (throws && strcmp (throws, "1") == 0)
741     function->throws = TRUE;
742   else
743     function->throws = FALSE;
744
745   if (ctx->current_node == NULL)
746     {
747       ctx->current_module->entries = 
748         g_list_append (ctx->current_module->entries, function);       
749     }
750   else
751     switch (ctx->current_node->type)
752       {
753       case G_IR_NODE_INTERFACE:
754       case G_IR_NODE_OBJECT:
755         {
756           GIrNodeInterface *iface;
757           
758           iface = (GIrNodeInterface *)ctx->current_node;
759           iface->members = g_list_append (iface->members, function);
760         }
761         break;
762       case G_IR_NODE_BOXED:
763         {
764           GIrNodeBoxed *boxed;
765           
766           boxed = (GIrNodeBoxed *)ctx->current_node;
767           boxed->members = g_list_append (boxed->members, function);
768         }
769         break;
770       case G_IR_NODE_STRUCT:
771         {
772           GIrNodeStruct *struct_;
773           
774           struct_ = (GIrNodeStruct *)ctx->current_node;
775           struct_->members = g_list_append (struct_->members, function);                }
776         break;
777       case G_IR_NODE_UNION:
778         {
779           GIrNodeUnion *union_;
780           
781           union_ = (GIrNodeUnion *)ctx->current_node;
782           union_->members = g_list_append (union_->members, function);
783         }
784         break;
785       default:
786         g_assert_not_reached ();
787       }
788   
789   ctx->current_node = (GIrNode *)function;
790   state_switch (ctx, STATE_FUNCTION);
791   
792   return TRUE;
793 }
794
795 static void
796 parse_param_transfer (GIrNodeParam *param, const gchar *transfer)
797 {
798   if (transfer == NULL)
799   {
800     g_warning ("required attribute 'transfer-ownership' missing");
801   }
802   else if (strcmp (transfer, "none") == 0)
803     {
804       param->transfer = FALSE;
805       param->shallow_transfer = FALSE;
806     }
807   else if (strcmp (transfer, "container") == 0)
808     {
809       param->transfer = FALSE;
810       param->shallow_transfer = TRUE;
811     }
812   else if (strcmp (transfer, "full") == 0)
813     {
814       param->transfer = TRUE;
815       param->shallow_transfer = FALSE;
816     }
817   else
818     {
819       g_warning ("Unknown transfer-ownership value: %s", transfer);
820     }
821 }
822
823 static gboolean
824 start_parameter (GMarkupParseContext *context,
825                  const gchar         *element_name,
826                  const gchar        **attribute_names,
827                  const gchar        **attribute_values,
828                  ParseContext        *ctx,
829                  GError             **error)
830 {
831   const gchar *name;
832   const gchar *direction;
833   const gchar *retval;
834   const gchar *dipper;
835   const gchar *optional;
836   const gchar *allow_none;
837   const gchar *transfer;
838   GIrNodeParam *param;
839       
840   if (!(strcmp (element_name, "parameter") == 0 &&
841         ctx->state == STATE_FUNCTION_PARAMETERS))
842     return FALSE;
843
844   name = find_attribute ("name", attribute_names, attribute_values);
845   direction = find_attribute ("direction", attribute_names, attribute_values);
846   retval = find_attribute ("retval", attribute_names, attribute_values);
847   dipper = find_attribute ("dipper", attribute_names, attribute_values);
848   optional = find_attribute ("optional", attribute_names, attribute_values);
849   allow_none = find_attribute ("allow-none", attribute_names, attribute_values);
850   transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
851
852   if (name == NULL)
853     name = "unknown";
854
855   param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
856
857   ctx->current_typed = (GIrNode*) param;
858   ctx->current_typed->name = g_strdup (name);
859
860   state_switch (ctx, STATE_FUNCTION_PARAMETER);
861
862   if (direction && strcmp (direction, "out") == 0)
863     {
864       param->in = FALSE;
865       param->out = TRUE;
866     }
867   else if (direction && strcmp (direction, "inout") == 0)
868     {
869       param->in = TRUE;
870       param->out = TRUE;
871     }
872   else
873     {
874       param->in = TRUE;
875       param->out = FALSE;
876     }
877
878   if (retval && strcmp (retval, "1") == 0)
879     param->retval = TRUE;
880   else
881     param->retval = FALSE;
882
883   if (dipper && strcmp (dipper, "1") == 0)
884     param->dipper = TRUE;
885   else
886     param->dipper = FALSE;
887
888   if (optional && strcmp (optional, "1") == 0)
889     param->optional = TRUE;
890   else
891     param->optional = FALSE;
892
893   if (allow_none && strcmp (allow_none, "1") == 0)
894     param->allow_none = TRUE;
895   else
896     param->allow_none = FALSE;
897
898   parse_param_transfer (param, transfer);
899
900   ((GIrNode *)param)->name = g_strdup (name);
901           
902   switch (ctx->current_node->type)
903     {
904     case G_IR_NODE_FUNCTION:
905     case G_IR_NODE_CALLBACK:
906       {
907         GIrNodeFunction *func;
908
909         func = (GIrNodeFunction *)ctx->current_node;
910         func->parameters = g_list_append (func->parameters, param);
911       }
912       break;
913     case G_IR_NODE_SIGNAL:
914       {
915         GIrNodeSignal *signal;
916
917         signal = (GIrNodeSignal *)ctx->current_node;
918         signal->parameters = g_list_append (signal->parameters, param);
919       }
920       break;
921     case G_IR_NODE_VFUNC:
922       {
923         GIrNodeVFunc *vfunc;
924                 
925         vfunc = (GIrNodeVFunc *)ctx->current_node;
926         vfunc->parameters = g_list_append (vfunc->parameters, param);
927       }
928       break;
929     default:
930       g_assert_not_reached ();
931     }
932
933   return TRUE;
934 }
935
936 static gboolean
937 start_field (GMarkupParseContext *context,
938              const gchar         *element_name,
939              const gchar        **attribute_names,
940              const gchar        **attribute_values,
941              ParseContext        *ctx,
942              GError             **error)
943 {
944   const gchar *name;
945   const gchar *readable;
946   const gchar *writable;
947   const gchar *bits;
948   const gchar *branch;
949   GIrNodeField *field;
950
951   switch (ctx->state)
952     {
953     case STATE_CLASS:
954     case STATE_BOXED:
955     case STATE_STRUCT:
956     case STATE_UNION:
957     case STATE_INTERFACE:
958       break;
959     default:
960       return FALSE;
961     }
962   
963   if (strcmp (element_name, "field") != 0)
964     return FALSE;
965   
966   name = find_attribute ("name", attribute_names, attribute_values);
967   readable = find_attribute ("readable", attribute_names, attribute_values);
968   writable = find_attribute ("writable", attribute_names, attribute_values);
969   bits = find_attribute ("bits", attribute_names, attribute_values);
970   branch = find_attribute ("branch", attribute_names, attribute_values);
971   
972   if (name == NULL)
973     {
974       MISSING_ATTRIBUTE (context, error, element_name, "name");
975       return FALSE;
976     }
977
978   field = (GIrNodeField *)g_ir_node_new (G_IR_NODE_FIELD);
979   ctx->current_typed = (GIrNode*) field;
980   ((GIrNode *)field)->name = g_strdup (name);
981   /* Fields are assumed to be read-only.
982    * (see also girwriter.py and generate.c)
983    */
984   field->readable = readable == NULL || strcmp (readable, "0") == 0;
985   field->writable = writable != NULL && strcmp (writable, "1") == 0;
986   
987   if (bits)
988     field->bits = atoi (bits);
989   else
990     field->bits = 0;
991   
992   switch (ctx->current_node->type)
993     {
994     case G_IR_NODE_OBJECT:
995       {
996         GIrNodeInterface *iface;
997         
998         iface = (GIrNodeInterface *)ctx->current_node;
999         iface->members = g_list_append (iface->members, field);
1000         state_switch (ctx, STATE_CLASS_FIELD);
1001       }
1002       break;
1003     case G_IR_NODE_INTERFACE:
1004       {
1005         GIrNodeInterface *iface;
1006         
1007         iface = (GIrNodeInterface *)ctx->current_node;
1008         iface->members = g_list_append (iface->members, field);
1009         state_switch (ctx, STATE_INTERFACE_FIELD);
1010       }
1011       break;
1012     case G_IR_NODE_BOXED:
1013       {
1014         GIrNodeBoxed *boxed;
1015         
1016         boxed = (GIrNodeBoxed *)ctx->current_node;
1017                 boxed->members = g_list_append (boxed->members, field);
1018                 state_switch (ctx, STATE_BOXED_FIELD);
1019       }
1020       break;
1021     case G_IR_NODE_STRUCT:
1022       {
1023         GIrNodeStruct *struct_;
1024         
1025         struct_ = (GIrNodeStruct *)ctx->current_node;
1026         struct_->members = g_list_append (struct_->members, field);
1027         state_switch (ctx, STATE_STRUCT_FIELD);
1028       }
1029       break;
1030     case G_IR_NODE_UNION:
1031       {
1032         GIrNodeUnion *union_;
1033         
1034         union_ = (GIrNodeUnion *)ctx->current_node;
1035         union_->members = g_list_append (union_->members, field);
1036         if (branch)
1037           {
1038             GIrNodeConstant *constant;
1039             
1040             constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1041             ((GIrNode *)constant)->name = g_strdup (name);
1042             constant->value = g_strdup (branch);          
1043             constant->type = union_->discriminator_type;
1044             constant->deprecated = FALSE;
1045             
1046             union_->discriminators = g_list_append (union_->discriminators, constant);
1047           }
1048         state_switch (ctx, STATE_UNION_FIELD);
1049       }
1050       break;
1051     default:
1052       g_assert_not_reached ();
1053     }
1054   
1055   return TRUE;
1056 }
1057
1058 static gboolean
1059 start_alias (GMarkupParseContext *context,
1060              const gchar         *element_name,
1061              const gchar        **attribute_names,
1062              const gchar        **attribute_values,
1063              ParseContext        *ctx,
1064              GError             **error)
1065 {
1066   const gchar *name;
1067   const gchar *target;
1068   char *key;
1069   char *value;
1070
1071   name = find_attribute ("name", attribute_names, attribute_values);
1072   if (name == NULL)
1073     {
1074       MISSING_ATTRIBUTE (context, error, element_name, "name");
1075       return FALSE;
1076     }
1077
1078   target = find_attribute ("target", attribute_names, attribute_values);
1079   if (name == NULL)
1080     {
1081       MISSING_ATTRIBUTE (context, error, element_name, "target");
1082       return FALSE;
1083     }
1084
1085   value = g_strdup (target);
1086   key = g_strdup_printf ("%s.%s", ctx->namespace, name);
1087   if (!strchr (target, '.'))
1088     {
1089       const BasicTypeInfo *basic = parse_basic (target);
1090       if (!basic)
1091         {
1092           g_free (value);
1093           /* For non-basic types, re-qualify the interface */
1094           value = g_strdup_printf ("%s.%s", ctx->namespace, target);
1095         }
1096     }
1097   g_hash_table_replace (ctx->aliases, key, value);
1098
1099   return TRUE;
1100 }
1101
1102 static gboolean
1103 start_enum (GMarkupParseContext *context,
1104              const gchar         *element_name,
1105              const gchar        **attribute_names,
1106              const gchar        **attribute_values,
1107              ParseContext        *ctx,
1108              GError             **error)
1109 {
1110   if ((strcmp (element_name, "enumeration") == 0 && ctx->state == STATE_NAMESPACE) ||
1111       (strcmp (element_name, "bitfield") == 0 && ctx->state == STATE_NAMESPACE))
1112     {
1113       const gchar *name;
1114       const gchar *typename;
1115       const gchar *typeinit;
1116       const gchar *deprecated;
1117       
1118       name = find_attribute ("name", attribute_names, attribute_values);
1119       typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1120       typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1121       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1122       
1123       if (name == NULL)
1124         MISSING_ATTRIBUTE (context, error, element_name, "name");
1125       else 
1126         {             
1127           GIrNodeEnum *enum_;
1128           
1129           if (strcmp (element_name, "enumeration") == 0)
1130             enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_ENUM);
1131           else
1132             enum_ = (GIrNodeEnum *) g_ir_node_new (G_IR_NODE_FLAGS);
1133           ((GIrNode *)enum_)->name = g_strdup (name);
1134           enum_->gtype_name = g_strdup (typename);
1135           enum_->gtype_init = g_strdup (typeinit);
1136           if (deprecated)
1137             enum_->deprecated = TRUE;
1138           else
1139             enum_->deprecated = FALSE;
1140
1141           ctx->current_node = (GIrNode *) enum_;
1142           ctx->current_module->entries = 
1143             g_list_append (ctx->current_module->entries, enum_);              
1144           
1145           state_switch (ctx, STATE_ENUM);
1146         }
1147       
1148       return TRUE;
1149     }
1150   return FALSE;
1151 }
1152
1153 static gboolean
1154 start_property (GMarkupParseContext *context,
1155                 const gchar         *element_name,
1156                 const gchar        **attribute_names,
1157                 const gchar        **attribute_values,
1158                 ParseContext        *ctx,
1159                 GError             **error)
1160 {
1161   if (strcmp (element_name, "property") == 0 &&
1162       (ctx->state == STATE_CLASS ||
1163        ctx->state == STATE_INTERFACE))
1164     {
1165       const gchar *name;
1166       const gchar *readable;
1167       const gchar *writable;
1168       const gchar *construct;
1169       const gchar *construct_only;
1170       
1171       name = find_attribute ("name", attribute_names, attribute_values);
1172       readable = find_attribute ("readable", attribute_names, attribute_values);
1173       writable = find_attribute ("writable", attribute_names, attribute_values);
1174       construct = find_attribute ("construct", attribute_names, attribute_values);
1175       construct_only = find_attribute ("construct-only", attribute_names, attribute_values);
1176       
1177       if (name == NULL)
1178         MISSING_ATTRIBUTE (context, error, element_name, "name");
1179       else 
1180         {             
1181           GIrNodeProperty *property;
1182           GIrNodeInterface *iface;
1183           
1184           property = (GIrNodeProperty *) g_ir_node_new (G_IR_NODE_PROPERTY);
1185           ctx->current_typed = (GIrNode*) property;
1186
1187           ((GIrNode *)property)->name = g_strdup (name);
1188           
1189           /* Assume properties are readable */
1190           if (readable == NULL || strcmp (readable, "1") == 0)
1191             property->readable = TRUE;
1192           else
1193             property->readable = FALSE;
1194           if (writable && strcmp (writable, "1") == 0)
1195             property->writable = TRUE;
1196           else
1197             property->writable = FALSE;
1198           if (construct && strcmp (construct, "1") == 0)
1199             property->construct = TRUE;
1200           else
1201             property->construct = FALSE;
1202           if (construct_only && strcmp (construct_only, "1") == 0)
1203             property->construct_only = TRUE;
1204           else
1205             property->construct_only = FALSE;
1206
1207           iface = (GIrNodeInterface *)ctx->current_node;
1208           iface->members = g_list_append (iface->members, property);
1209
1210           if (ctx->state == STATE_CLASS)
1211             state_switch (ctx, STATE_CLASS_PROPERTY);
1212           else if (ctx->state == STATE_INTERFACE)
1213             state_switch (ctx, STATE_INTERFACE_PROPERTY);
1214           else
1215             g_assert_not_reached ();
1216         }
1217       
1218       return TRUE;
1219     }
1220   return FALSE;
1221 }
1222
1223 static gint
1224 parse_value (const gchar *str)
1225 {
1226   gchar *shift_op;
1227  
1228   /* FIXME just a quick hack */
1229   shift_op = strstr (str, "<<");
1230
1231   if (shift_op)
1232     {
1233       gint base, shift;
1234
1235       base = strtol (str, NULL, 10);
1236       shift = strtol (shift_op + 3, NULL, 10);
1237       
1238       return base << shift;
1239     }
1240   else
1241     return strtol (str, NULL, 10);
1242
1243   return 0;
1244 }
1245
1246 static gboolean
1247 start_member (GMarkupParseContext *context,
1248               const gchar         *element_name,
1249               const gchar        **attribute_names,
1250               const gchar        **attribute_values,
1251               ParseContext        *ctx,
1252               GError             **error)
1253 {
1254   if (strcmp (element_name, "member") == 0 &&
1255       ctx->state == STATE_ENUM)
1256     {
1257       const gchar *name;
1258       const gchar *value;
1259       const gchar *deprecated;
1260       
1261       name = find_attribute ("name", attribute_names, attribute_values);
1262       value = find_attribute ("value", attribute_names, attribute_values);
1263       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1264       
1265       if (name == NULL)
1266         MISSING_ATTRIBUTE (context, error, element_name, "name");
1267       else 
1268         {             
1269           GIrNodeEnum *enum_;
1270           GIrNodeValue *value_;
1271
1272           value_ = (GIrNodeValue *) g_ir_node_new (G_IR_NODE_VALUE);
1273
1274           ((GIrNode *)value_)->name = g_strdup (name);
1275           
1276           value_->value = parse_value (value);
1277           
1278           if (deprecated)
1279             value_->deprecated = TRUE;
1280           else
1281             value_->deprecated = FALSE;
1282
1283           enum_ = (GIrNodeEnum *)ctx->current_node;
1284           enum_->values = g_list_append (enum_->values, value_);
1285         }
1286       
1287       return TRUE;
1288     }
1289   return FALSE;
1290 }
1291
1292 static gboolean
1293 start_constant (GMarkupParseContext *context,
1294                 const gchar         *element_name,
1295                 const gchar        **attribute_names,
1296                 const gchar        **attribute_values,
1297                 ParseContext        *ctx,
1298                 GError             **error)
1299 {
1300   if (strcmp (element_name, "constant") == 0 &&
1301       (ctx->state == STATE_NAMESPACE ||
1302        ctx->state == STATE_CLASS ||
1303        ctx->state == STATE_INTERFACE))
1304     {
1305       const gchar *name;
1306       const gchar *value;
1307       const gchar *deprecated;
1308       
1309       name = find_attribute ("name", attribute_names, attribute_values);
1310       value = find_attribute ("value", attribute_names, attribute_values);
1311       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1312       
1313       if (name == NULL)
1314         MISSING_ATTRIBUTE (context, error, element_name, "name");
1315       else if (value == NULL)
1316         MISSING_ATTRIBUTE (context, error, element_name, "value");
1317       else 
1318         {             
1319           GIrNodeConstant *constant;
1320
1321           constant = (GIrNodeConstant *) g_ir_node_new (G_IR_NODE_CONSTANT);
1322
1323           ((GIrNode *)constant)->name = g_strdup (name);
1324           constant->value = g_strdup (value);
1325
1326           ctx->current_typed = (GIrNode*) constant;
1327
1328           if (deprecated)
1329             constant->deprecated = TRUE;
1330           else
1331             constant->deprecated = FALSE;
1332
1333           if (ctx->state == STATE_NAMESPACE)
1334             {
1335               ctx->current_node = (GIrNode *) constant;
1336               ctx->current_module->entries = 
1337                 g_list_append (ctx->current_module->entries, constant);
1338             }
1339           else
1340             {
1341               GIrNodeInterface *iface;
1342
1343               iface = (GIrNodeInterface *)ctx->current_node;
1344               iface->members = g_list_append (iface->members, constant);
1345             }
1346
1347           switch (ctx->state)
1348             {
1349             case STATE_NAMESPACE:
1350               state_switch (ctx, STATE_NAMESPACE_CONSTANT);
1351               break;
1352             case STATE_CLASS:
1353               state_switch (ctx, STATE_CLASS_CONSTANT);
1354               break;
1355             case STATE_INTERFACE:
1356               state_switch (ctx, STATE_INTERFACE_CONSTANT);
1357               break;
1358             default:
1359               g_assert_not_reached ();
1360               break;
1361             }
1362         }
1363       
1364       return TRUE;
1365     }
1366   return FALSE;
1367 }
1368
1369 static gboolean
1370 start_errordomain (GMarkupParseContext *context,
1371                    const gchar         *element_name,
1372                    const gchar        **attribute_names,
1373                    const gchar        **attribute_values,
1374                    ParseContext        *ctx,
1375                    GError             **error)
1376 {
1377   if (strcmp (element_name, "errordomain") == 0 &&
1378       ctx->state == STATE_NAMESPACE)
1379     {
1380       const gchar *name;
1381       const gchar *getquark;
1382       const gchar *codes;
1383       const gchar *deprecated;
1384       
1385       name = find_attribute ("name", attribute_names, attribute_values);
1386       getquark = find_attribute ("get-quark", attribute_names, attribute_values);
1387       codes = find_attribute ("codes", attribute_names, attribute_values);
1388       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1389       
1390       if (name == NULL)
1391         MISSING_ATTRIBUTE (context, error, element_name, "name");
1392       else if (getquark == NULL)
1393         MISSING_ATTRIBUTE (context, error, element_name, "getquark");
1394       else if (codes == NULL)
1395         MISSING_ATTRIBUTE (context, error, element_name, "codes");
1396       else 
1397         {             
1398           GIrNodeErrorDomain *domain;
1399
1400           domain = (GIrNodeErrorDomain *) g_ir_node_new (G_IR_NODE_ERROR_DOMAIN);
1401
1402           ((GIrNode *)domain)->name = g_strdup (name);
1403           domain->getquark = g_strdup (getquark);
1404           domain->codes = g_strdup (codes);
1405
1406           if (deprecated)
1407             domain->deprecated = TRUE;
1408           else
1409             domain->deprecated = FALSE;
1410
1411           ctx->current_node = (GIrNode *) domain;
1412           ctx->current_module->entries = 
1413             g_list_append (ctx->current_module->entries, domain);
1414
1415           state_switch (ctx, STATE_ERRORDOMAIN);
1416         }
1417       
1418       return TRUE;
1419     }
1420   return FALSE;
1421 }
1422
1423 static gboolean
1424 start_interface (GMarkupParseContext *context,
1425                  const gchar         *element_name,
1426                  const gchar        **attribute_names,
1427                  const gchar        **attribute_values,
1428                  ParseContext        *ctx,
1429                  GError             **error)
1430 {
1431   if (strcmp (element_name, "interface") == 0 &&
1432       ctx->state == STATE_NAMESPACE)
1433     {
1434       const gchar *name;
1435       const gchar *typename;
1436       const gchar *typeinit;
1437       const gchar *deprecated;
1438       
1439       name = find_attribute ("name", attribute_names, attribute_values);
1440       typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1441       typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1442       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1443       
1444       if (name == NULL)
1445         MISSING_ATTRIBUTE (context, error, element_name, "name");
1446       else if (typename == NULL)
1447         MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1448       else if (typeinit == NULL)
1449         MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1450       else
1451         {
1452           GIrNodeInterface *iface;
1453
1454           iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_INTERFACE);
1455           ((GIrNode *)iface)->name = g_strdup (name);
1456           iface->gtype_name = g_strdup (typename);
1457           iface->gtype_init = g_strdup (typeinit);
1458           if (deprecated)
1459             iface->deprecated = TRUE;
1460           else
1461             iface->deprecated = FALSE;
1462           
1463           ctx->current_node = (GIrNode *) iface;
1464           ctx->current_module->entries = 
1465             g_list_append (ctx->current_module->entries, iface);              
1466           
1467           state_switch (ctx, STATE_INTERFACE);
1468           
1469         }
1470       
1471       return TRUE;
1472     }
1473   return FALSE;
1474 }
1475
1476 static gboolean
1477 start_class (GMarkupParseContext *context,
1478               const gchar         *element_name,
1479               const gchar        **attribute_names,
1480               const gchar        **attribute_values,
1481               ParseContext        *ctx,
1482               GError             **error)
1483 {
1484   if (strcmp (element_name, "class") == 0 &&
1485       ctx->state == STATE_NAMESPACE)
1486     {
1487       const gchar *name;
1488       const gchar *parent;
1489       const gchar *typename;
1490       const gchar *typeinit;
1491       const gchar *deprecated;
1492       const gchar *abstract;
1493       
1494       name = find_attribute ("name", attribute_names, attribute_values);
1495       parent = find_attribute ("parent", attribute_names, attribute_values);
1496       typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
1497       typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
1498       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
1499       abstract = find_attribute ("abstract", attribute_names, attribute_values);
1500       
1501       if (name == NULL)
1502         MISSING_ATTRIBUTE (context, error, element_name, "name");
1503       else if (typename == NULL)
1504         MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
1505       else if (typeinit == NULL && strcmp (typename, "GObject"))
1506         MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
1507       else
1508         {
1509           GIrNodeInterface *iface;
1510
1511           iface = (GIrNodeInterface *) g_ir_node_new (G_IR_NODE_OBJECT);
1512           ((GIrNode *)iface)->name = g_strdup (name);
1513           iface->gtype_name = g_strdup (typename);
1514           iface->gtype_init = g_strdup (typeinit);
1515           iface->parent = g_strdup (parent);
1516           if (deprecated)
1517             iface->deprecated = TRUE;
1518           else
1519             iface->deprecated = FALSE;
1520
1521           iface->abstract = abstract && strcmp (abstract, "1") == 0;
1522
1523           ctx->current_node = (GIrNode *) iface;
1524           ctx->current_module->entries = 
1525             g_list_append (ctx->current_module->entries, iface);              
1526           
1527           state_switch (ctx, STATE_CLASS);
1528         }
1529       
1530       return TRUE;
1531     }
1532   return  FALSE;
1533 }
1534
1535 static gboolean
1536 start_type (GMarkupParseContext *context,
1537             const gchar         *element_name,
1538             const gchar        **attribute_names,
1539             const gchar        **attribute_values,
1540             ParseContext       *ctx,
1541             GError             **error)
1542 {
1543   const gchar *name;
1544   const gchar *ctype;
1545   gboolean is_array;
1546   gboolean is_varargs;
1547   GIrNodeType *typenode;
1548
1549   is_array = strcmp (element_name, "array") == 0;
1550   is_varargs = strcmp (element_name, "varargs") == 0;
1551
1552   if (!(is_array || is_varargs || (strcmp (element_name, "type") == 0)))
1553     return FALSE;
1554
1555   if (ctx->state == STATE_TYPE) 
1556     {
1557       ctx->type_depth++;
1558       ctx->type_stack = g_list_prepend (ctx->type_stack, ctx->type_parameters);
1559       ctx->type_parameters = NULL;
1560     } 
1561   else if (ctx->state == STATE_FUNCTION_PARAMETER ||
1562            ctx->state == STATE_FUNCTION_RETURN || 
1563            ctx->state == STATE_STRUCT_FIELD ||
1564            ctx->state == STATE_UNION_FIELD ||
1565            ctx->state == STATE_CLASS_PROPERTY ||
1566            ctx->state == STATE_CLASS_FIELD ||
1567            ctx->state == STATE_INTERFACE_FIELD ||
1568            ctx->state == STATE_INTERFACE_PROPERTY ||
1569            ctx->state == STATE_BOXED_FIELD ||
1570            ctx->state == STATE_NAMESPACE_CONSTANT ||
1571            ctx->state == STATE_CLASS_CONSTANT ||
1572            ctx->state == STATE_INTERFACE_CONSTANT
1573            )
1574     {
1575       state_switch (ctx, STATE_TYPE);
1576       ctx->type_depth = 1;
1577       if (is_varargs)
1578         {
1579           switch (ctx->current_node->type)
1580             {
1581             case G_IR_NODE_FUNCTION:
1582             case G_IR_NODE_CALLBACK:
1583               {
1584                 GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1585                 func->is_varargs = TRUE;
1586               }
1587               break;
1588             case G_IR_NODE_VFUNC:
1589               {
1590                 GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1591                 vfunc->is_varargs = TRUE;
1592               }
1593               break;
1594             /* list others individually rather than with default: so that compiler
1595              * warns if new node types are added without adding them to the switch
1596              */
1597             case G_IR_NODE_INVALID:
1598             case G_IR_NODE_ENUM:
1599             case G_IR_NODE_FLAGS:
1600             case G_IR_NODE_CONSTANT:
1601             case G_IR_NODE_ERROR_DOMAIN:
1602             case G_IR_NODE_PARAM:
1603             case G_IR_NODE_TYPE:
1604             case G_IR_NODE_PROPERTY:
1605             case G_IR_NODE_SIGNAL:
1606             case G_IR_NODE_VALUE:
1607             case G_IR_NODE_FIELD:
1608             case G_IR_NODE_XREF:
1609             case G_IR_NODE_STRUCT:
1610             case G_IR_NODE_BOXED:
1611             case G_IR_NODE_OBJECT:
1612             case G_IR_NODE_INTERFACE:
1613             case G_IR_NODE_UNION:
1614               g_assert_not_reached ();
1615               break;
1616             }
1617         }
1618       ctx->type_stack = NULL;
1619       ctx->type_parameters = NULL;
1620     }
1621
1622   if (!ctx->current_typed)
1623     {
1624       g_set_error (error,
1625                    G_MARKUP_ERROR,
1626                    G_MARKUP_ERROR_INVALID_CONTENT,
1627                    "The element <type> is invalid here");
1628       return FALSE;
1629     }
1630
1631   if (is_varargs)
1632     return TRUE;
1633
1634   if (is_array) 
1635     {
1636       const char *zero;
1637       const char *len;
1638       const char *size;
1639
1640       typenode = (GIrNodeType *)g_ir_node_new (G_IR_NODE_TYPE);
1641
1642       typenode->tag = GI_TYPE_TAG_ARRAY;
1643       typenode->is_pointer = TRUE;
1644       typenode->is_array = TRUE;
1645       
1646       zero = find_attribute ("zero-terminated", attribute_names, attribute_values);
1647       len = find_attribute ("length", attribute_names, attribute_values);
1648       size = find_attribute ("fixed-size", attribute_names, attribute_values);
1649       
1650       typenode->zero_terminated = !(zero && strcmp (zero, "1") != 0);
1651       typenode->has_length = len != NULL;
1652       typenode->length = typenode->has_length ? atoi (len) : -1;
1653       
1654       typenode->has_size = size != NULL;
1655       typenode->size = typenode->has_size ? atoi (size) : -1;
1656     }
1657   else
1658     {
1659       int pointer_depth;
1660       name = find_attribute ("name", attribute_names, attribute_values);
1661
1662       if (name == NULL)
1663         MISSING_ATTRIBUTE (context, error, element_name, "name");
1664       
1665       pointer_depth = 0;
1666       ctype = find_attribute ("c:type", attribute_names, attribute_values);
1667       if (ctype != NULL)
1668         {
1669           const char *cp = ctype + strlen(ctype) - 1;
1670           while (cp > ctype && *cp-- == '*')
1671             pointer_depth++;
1672         }
1673       
1674       if (ctx->current_typed->type == G_IR_NODE_PARAM &&
1675           ((GIrNodeParam *)ctx->current_typed)->out &&
1676           pointer_depth > 0)
1677         pointer_depth--;
1678       
1679       typenode = parse_type (ctx, name);
1680
1681       /* A 'disguised' structure is one where the c:type is a typedef that
1682        * doesn't look like a pointer, but is internally.
1683        */
1684       if (typenode->tag == GI_TYPE_TAG_INTERFACE &&
1685           is_disguised_structure (ctx, typenode->interface))
1686         pointer_depth++;
1687
1688       if (pointer_depth > 0)
1689         typenode->is_pointer = TRUE;
1690     }
1691
1692   ctx->type_parameters = g_list_append (ctx->type_parameters, typenode);
1693   
1694   return TRUE;
1695 }
1696
1697 static void
1698 end_type_top (ParseContext *ctx)
1699 {
1700   GIrNodeType *typenode;
1701
1702   if (!ctx->type_parameters)
1703     goto out;
1704
1705   typenode = (GIrNodeType*)ctx->type_parameters->data;
1706
1707   /* Default to pointer for unspecified containers */
1708   if (typenode->tag == GI_TYPE_TAG_ARRAY ||
1709       typenode->tag == GI_TYPE_TAG_GLIST ||
1710       typenode->tag == GI_TYPE_TAG_GSLIST)
1711     {
1712       if (typenode->parameter_type1 == NULL)
1713         typenode->parameter_type1 = parse_type (ctx, "any");
1714     }
1715   else if (typenode->tag == GI_TYPE_TAG_GHASH)
1716     {
1717       if (typenode->parameter_type1 == NULL)
1718         {
1719           typenode->parameter_type1 = parse_type (ctx, "any");
1720           typenode->parameter_type2 = parse_type (ctx, "any");
1721         }
1722     }
1723
1724   switch (ctx->current_typed->type)
1725     {
1726     case G_IR_NODE_PARAM:
1727       {
1728         GIrNodeParam *param = (GIrNodeParam *)ctx->current_typed;
1729         param->type = typenode;
1730       }
1731       break;
1732     case G_IR_NODE_FIELD:
1733       {
1734         GIrNodeField *field = (GIrNodeField *)ctx->current_typed;
1735         field->type = typenode;
1736       }
1737       break;
1738     case G_IR_NODE_PROPERTY:
1739       {
1740         GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed;
1741         property->type = typenode;
1742       }
1743       break;
1744     case G_IR_NODE_CONSTANT:
1745       {
1746         GIrNodeConstant *constant = (GIrNodeConstant *)ctx->current_typed;
1747         constant->type = typenode;
1748       }
1749       break;
1750     default:
1751       g_printerr("current node is %d\n", ctx->current_node->type);
1752       g_assert_not_reached ();
1753     }
1754   g_list_free (ctx->type_parameters);
1755
1756  out:  
1757   ctx->type_depth = 0;
1758   ctx->type_parameters = NULL;
1759   ctx->current_typed = NULL;
1760 }
1761
1762 static void
1763 end_type_recurse (ParseContext *ctx)
1764 {
1765   GIrNodeType *parent;
1766   GIrNodeType *param = NULL;
1767
1768   parent = (GIrNodeType *) ((GList*)ctx->type_stack->data)->data;
1769   if (ctx->type_parameters)
1770     param = (GIrNodeType *) ctx->type_parameters->data;
1771
1772   if (parent->tag == GI_TYPE_TAG_ARRAY ||
1773       parent->tag == GI_TYPE_TAG_GLIST ||
1774       parent->tag == GI_TYPE_TAG_GSLIST)
1775     {
1776       g_assert (param != NULL);
1777
1778       if (parent->parameter_type1 == NULL)
1779         parent->parameter_type1 = param;
1780       else
1781         g_assert_not_reached ();
1782     }
1783   else if (parent->tag == GI_TYPE_TAG_GHASH)
1784     {
1785       g_assert (param != NULL);
1786
1787       if (parent->parameter_type1 == NULL)
1788         parent->parameter_type1 = param;
1789       else if (parent->parameter_type2 == NULL)
1790         parent->parameter_type2 = param;
1791       else
1792         g_assert_not_reached ();
1793     }
1794   g_list_free (ctx->type_parameters);
1795   ctx->type_parameters = (GList *)ctx->type_stack->data;
1796   ctx->type_stack = g_list_delete_link (ctx->type_stack, ctx->type_stack);
1797 }
1798
1799 static void
1800 end_type (ParseContext *ctx)
1801 {
1802   if (ctx->type_depth == 1)
1803     {
1804       end_type_top (ctx);
1805       state_switch (ctx, ctx->prev_state);
1806     }
1807   else
1808     {
1809       end_type_recurse (ctx);
1810       ctx->type_depth--;
1811     }
1812 }
1813
1814 static gboolean
1815 start_return_value (GMarkupParseContext *context,
1816                     const gchar         *element_name,
1817                     const gchar        **attribute_names,
1818                     const gchar        **attribute_values,
1819                     ParseContext       *ctx,
1820                     GError             **error)
1821 {
1822   if (strcmp (element_name, "return-value") == 0 &&
1823       ctx->state == STATE_FUNCTION)
1824     {
1825       GIrNodeParam *param;
1826       const gchar  *transfer;
1827
1828       param = (GIrNodeParam *)g_ir_node_new (G_IR_NODE_PARAM);
1829       param->in = FALSE;
1830       param->out = FALSE;
1831       param->retval = TRUE;
1832
1833       ctx->current_typed = (GIrNode*) param;
1834
1835       state_switch (ctx, STATE_FUNCTION_RETURN);
1836
1837       transfer = find_attribute ("transfer-ownership", attribute_names, attribute_values);
1838       parse_param_transfer (param, transfer);
1839
1840       switch (ctx->current_node->type)
1841         {
1842         case G_IR_NODE_FUNCTION:
1843         case G_IR_NODE_CALLBACK:
1844           {
1845             GIrNodeFunction *func = (GIrNodeFunction *)ctx->current_node;
1846             func->result = param;
1847           }
1848           break;
1849         case G_IR_NODE_SIGNAL:
1850           {
1851             GIrNodeSignal *signal = (GIrNodeSignal *)ctx->current_node;
1852             signal->result = param;
1853           }
1854           break;
1855         case G_IR_NODE_VFUNC:
1856           {
1857             GIrNodeVFunc *vfunc = (GIrNodeVFunc *)ctx->current_node;
1858             vfunc->result = param;
1859           }
1860           break;
1861         default:
1862           g_assert_not_reached ();
1863         }
1864       
1865       return TRUE;
1866     }
1867
1868   return FALSE;
1869 }
1870
1871 static gboolean
1872 start_implements (GMarkupParseContext *context,
1873                   const gchar         *element_name,
1874                   const gchar        **attribute_names,
1875                   const gchar        **attribute_values,
1876                   ParseContext       *ctx,
1877                   GError             **error)
1878 {
1879   GIrNodeInterface *iface;
1880   const char *name;
1881
1882   if (strcmp (element_name, "implements") != 0 ||
1883       !(ctx->state == STATE_CLASS))
1884     return FALSE;
1885
1886   state_switch (ctx, STATE_IMPLEMENTS);
1887   
1888   name = find_attribute ("name", attribute_names, attribute_values);
1889   if (name == NULL)
1890     {
1891       MISSING_ATTRIBUTE (context, error, element_name, "name");
1892       return FALSE;
1893     }
1894       
1895   iface = (GIrNodeInterface *)ctx->current_node;
1896   iface->interfaces = g_list_append (iface->interfaces, g_strdup (name));
1897
1898   return TRUE;
1899 }
1900
1901 static gboolean
1902 start_glib_signal (GMarkupParseContext *context,
1903                    const gchar         *element_name,
1904                    const gchar        **attribute_names,
1905                    const gchar        **attribute_values,
1906                    ParseContext       *ctx,
1907                    GError             **error)
1908 {
1909   if (strcmp (element_name, "glib:signal") == 0 && 
1910       (ctx->state == STATE_CLASS ||
1911        ctx->state == STATE_INTERFACE))
1912     {
1913       const gchar *name;
1914       const gchar *when;
1915       const gchar *no_recurse;
1916       const gchar *detailed;
1917       const gchar *action;
1918       const gchar *no_hooks;
1919       const gchar *has_class_closure;
1920       
1921       name = find_attribute ("name", attribute_names, attribute_values);
1922       when = find_attribute ("when", attribute_names, attribute_values);
1923       no_recurse = find_attribute ("no-recurse", attribute_names, attribute_values);
1924       detailed = find_attribute ("detailed", attribute_names, attribute_values);
1925       action = find_attribute ("action", attribute_names, attribute_values);
1926       no_hooks = find_attribute ("no-hooks", attribute_names, attribute_values);
1927       has_class_closure = find_attribute ("has-class-closure", attribute_names, attribute_values);
1928       
1929       if (name == NULL)
1930         MISSING_ATTRIBUTE (context, error, element_name, "name");
1931       else
1932         {
1933           GIrNodeInterface *iface;
1934           GIrNodeSignal *signal;
1935
1936           signal = (GIrNodeSignal *)g_ir_node_new (G_IR_NODE_SIGNAL);
1937           
1938           ((GIrNode *)signal)->name = g_strdup (name);
1939           
1940           signal->run_first = FALSE;
1941           signal->run_last = FALSE;
1942           signal->run_cleanup = FALSE;
1943           if (when == NULL || strcmp (when, "LAST") == 0)
1944             signal->run_last = TRUE;
1945           else if (strcmp (when, "FIRST") == 0)
1946             signal->run_first = TRUE;
1947           else 
1948             signal->run_cleanup = TRUE;
1949           
1950           if (no_recurse && strcmp (no_recurse, "1") == 0)
1951             signal->no_recurse = TRUE;
1952           else
1953             signal->no_recurse = FALSE;
1954           if (detailed && strcmp (detailed, "1") == 0)
1955             signal->detailed = TRUE;
1956           else
1957             signal->detailed = FALSE;
1958           if (action && strcmp (action, "1") == 0)
1959             signal->action = TRUE;
1960           else
1961             signal->action = FALSE;
1962           if (no_hooks && strcmp (no_hooks, "1") == 0)
1963             signal->no_hooks = TRUE;
1964           else
1965             signal->no_hooks = FALSE;
1966           if (has_class_closure && strcmp (has_class_closure, "1") == 0)
1967             signal->has_class_closure = TRUE;
1968           else
1969             signal->has_class_closure = FALSE;
1970
1971           iface = (GIrNodeInterface *)ctx->current_node;
1972           iface->members = g_list_append (iface->members, signal);
1973
1974           ctx->current_node = (GIrNode *)signal;
1975           state_switch (ctx, STATE_FUNCTION);
1976         }
1977       
1978       return TRUE;
1979     }
1980   return FALSE;
1981 }
1982
1983 static gboolean
1984 start_vfunc (GMarkupParseContext *context,
1985              const gchar         *element_name,
1986              const gchar        **attribute_names,
1987              const gchar        **attribute_values,
1988              ParseContext       *ctx,
1989              GError             **error)
1990 {
1991   if (strcmp (element_name, "vfunc") == 0 && 
1992       (ctx->state == STATE_CLASS ||
1993        ctx->state == STATE_INTERFACE))
1994     {
1995       const gchar *name;
1996       const gchar *must_chain_up;
1997       const gchar *override;
1998       const gchar *is_class_closure;
1999       const gchar *offset;
2000       
2001       name = find_attribute ("name", attribute_names, attribute_values);
2002       must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values);        
2003       override = find_attribute ("override", attribute_names, attribute_values);
2004       is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values);
2005       offset = find_attribute ("offset", attribute_names, attribute_values);
2006       
2007       if (name == NULL)
2008         MISSING_ATTRIBUTE (context, error, element_name, "name");
2009       else
2010         {
2011           GIrNodeInterface *iface;
2012           GIrNodeVFunc *vfunc;
2013
2014           vfunc = (GIrNodeVFunc *)g_ir_node_new (G_IR_NODE_VFUNC);
2015           
2016           ((GIrNode *)vfunc)->name = g_strdup (name);
2017
2018           if (must_chain_up && strcmp (must_chain_up, "1") == 0)
2019             vfunc->must_chain_up = TRUE;
2020           else
2021             vfunc->must_chain_up = FALSE;
2022
2023           if (override && strcmp (override, "always") == 0)
2024             {
2025               vfunc->must_be_implemented = TRUE;
2026               vfunc->must_not_be_implemented = FALSE;
2027             }
2028           else if (override && strcmp (override, "never") == 0)
2029             {
2030               vfunc->must_be_implemented = FALSE;
2031               vfunc->must_not_be_implemented = TRUE;
2032             }
2033           else
2034             {
2035               vfunc->must_be_implemented = FALSE;
2036               vfunc->must_not_be_implemented = FALSE;
2037             }
2038           
2039           if (is_class_closure && strcmp (is_class_closure, "1") == 0)
2040             vfunc->is_class_closure = TRUE;
2041           else
2042             vfunc->is_class_closure = FALSE;
2043           
2044           if (offset)
2045             vfunc->offset = atoi (offset);
2046           else
2047             vfunc->offset = 0;
2048
2049           iface = (GIrNodeInterface *)ctx->current_node;
2050           iface->members = g_list_append (iface->members, vfunc);
2051
2052           ctx->current_node = (GIrNode *)vfunc;
2053           state_switch (ctx, STATE_FUNCTION);
2054         }
2055       
2056       return TRUE;
2057     }
2058   return FALSE;
2059 }
2060
2061
2062 static gboolean
2063 start_struct (GMarkupParseContext *context,
2064               const gchar         *element_name,
2065               const gchar        **attribute_names,
2066               const gchar        **attribute_values,
2067               ParseContext       *ctx,
2068               GError             **error)
2069 {
2070   if (strcmp (element_name, "record") == 0 && 
2071       ctx->state == STATE_NAMESPACE)
2072     {
2073       const gchar *name;
2074       const gchar *deprecated;
2075       const gchar *disguised;
2076       const gchar *gtype_name;
2077       const gchar *gtype_init;
2078       GIrNodeStruct *struct_;
2079       
2080       name = find_attribute ("name", attribute_names, attribute_values);
2081       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
2082       disguised = find_attribute ("disguised", attribute_names, attribute_values);
2083       gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values);
2084       gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values);
2085
2086       if (name == NULL)
2087         {
2088           MISSING_ATTRIBUTE (context, error, element_name, "name");
2089           return FALSE;
2090         }
2091       if ((gtype_name == NULL && gtype_init != NULL))
2092         {
2093           MISSING_ATTRIBUTE (context, error, element_name, "glib:type-name");
2094           return FALSE;
2095         }
2096       if ((gtype_name != NULL && gtype_init == NULL))
2097         {
2098           MISSING_ATTRIBUTE (context, error, element_name, "glib:get-type");
2099           return FALSE;
2100         }
2101
2102       struct_ = (GIrNodeStruct *) g_ir_node_new (G_IR_NODE_STRUCT);
2103       
2104       ((GIrNode *)struct_)->name = g_strdup (name);
2105       if (deprecated)
2106         struct_->deprecated = TRUE;
2107       else
2108         struct_->deprecated = FALSE;
2109
2110       if (disguised && strcmp (disguised, "1") == 0)
2111         struct_->disguised = TRUE;
2112
2113       struct_->gtype_name = g_strdup (gtype_name);
2114       struct_->gtype_init = g_strdup (gtype_init);
2115       
2116       ctx->current_node = (GIrNode *)struct_;
2117       ctx->current_module->entries = 
2118         g_list_append (ctx->current_module->entries, struct_);
2119       
2120       state_switch (ctx, STATE_STRUCT);
2121       return TRUE;
2122     }
2123   return FALSE;
2124 }
2125   
2126
2127 static gboolean
2128 start_union (GMarkupParseContext *context,
2129              const gchar         *element_name,
2130              const gchar        **attribute_names,
2131              const gchar        **attribute_values,
2132              ParseContext       *ctx,
2133              GError             **error)
2134 {
2135   if (strcmp (element_name, "union") == 0 && 
2136       ctx->state == STATE_NAMESPACE)
2137     {
2138       const gchar *name;
2139       const gchar *deprecated;
2140       const gchar *typename;
2141       const gchar *typeinit;
2142       
2143       name = find_attribute ("name", attribute_names, attribute_values);
2144       deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
2145       typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
2146       typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
2147       
2148       if (name == NULL)
2149         MISSING_ATTRIBUTE (context, error, element_name, "name");
2150       else
2151         {
2152           GIrNodeUnion *union_;
2153
2154           union_ = (GIrNodeUnion *) g_ir_node_new (G_IR_NODE_UNION);
2155           
2156           ((GIrNode *)union_)->name = g_strdup (name);
2157           union_->gtype_name = g_strdup (typename);
2158           union_->gtype_init = g_strdup (typeinit);
2159           if (deprecated)
2160             union_->deprecated = TRUE;
2161           else
2162             union_->deprecated = FALSE;
2163
2164           ctx->current_node = (GIrNode *)union_;
2165           ctx->current_module->entries = 
2166             g_list_append (ctx->current_module->entries, union_);
2167           
2168           state_switch (ctx, STATE_UNION);
2169         }
2170       return TRUE;
2171     }
2172   return FALSE;
2173 }
2174
2175 static gboolean
2176 start_discriminator (GMarkupParseContext *context,
2177                      const gchar         *element_name,
2178                      const gchar        **attribute_names,
2179                      const gchar        **attribute_values,
2180                      ParseContext       *ctx,
2181                      GError             **error)
2182 {
2183   if (strcmp (element_name, "discriminator") == 0 &&
2184       ctx->state == STATE_UNION)
2185     {
2186       const gchar *type;
2187       const gchar *offset;
2188       
2189       type = find_attribute ("type", attribute_names, attribute_values);
2190       offset = find_attribute ("offset", attribute_names, attribute_values);
2191       if (type == NULL)
2192         MISSING_ATTRIBUTE (context, error, element_name, "type");
2193       else if (offset == NULL)
2194         MISSING_ATTRIBUTE (context, error, element_name, "offset");
2195         {
2196           ((GIrNodeUnion *)ctx->current_node)->discriminator_type 
2197             = parse_type (ctx, type);
2198           ((GIrNodeUnion *)ctx->current_node)->discriminator_offset 
2199             = atoi (offset);
2200         }
2201       
2202       return TRUE;
2203     }
2204
2205   return FALSE;
2206 }
2207
2208 static gboolean
2209 parse_include (GMarkupParseContext *context,
2210                ParseContext        *ctx,
2211                const char          *name,
2212                const char          *version,
2213                GError             **error)
2214 {
2215   gchar *buffer;
2216   gsize length;
2217   char *girpath;
2218   gboolean success = FALSE;
2219   GList *modules;
2220   GList *l;
2221
2222   for (l = ctx->parser->parsed_modules; l; l = l->next)
2223     {
2224       GIrModule *m = l->data;
2225
2226       if (strcmp (m->name, name) == 0)
2227         {
2228           if (strcmp (m->version, version) == 0)
2229             {
2230               ctx->include_modules = g_list_prepend (ctx->include_modules, m);
2231
2232               return TRUE;
2233             }
2234           else
2235             {
2236               g_set_error (error,
2237                            G_MARKUP_ERROR,
2238                            G_MARKUP_ERROR_INVALID_CONTENT,
2239                            "Module '%s' imported with conflicting versions '%s' and '%s'",
2240                            name, m->version, version);
2241               return FALSE;
2242             }
2243         }
2244     }
2245
2246   girpath = locate_gir (ctx->parser, name, version);
2247
2248   if (girpath == NULL)
2249     {
2250       g_set_error (error,
2251                    G_MARKUP_ERROR,
2252                    G_MARKUP_ERROR_INVALID_CONTENT,
2253                    "Could not find GIR file '%s.gir'; check XDG_DATA_DIRS or use --includedir",
2254                    name);
2255       return FALSE;
2256     }
2257
2258   g_debug ("Parsing include %s", girpath);
2259
2260   if (!g_file_get_contents (girpath, &buffer, &length, error))
2261     {
2262       g_free (girpath);
2263       return FALSE;
2264     }
2265   g_free (girpath);
2266
2267   modules = g_ir_parser_parse_string (ctx->parser, name, buffer, length, error);
2268   success = error != NULL;
2269
2270   ctx->include_modules = g_list_concat (ctx->include_modules,
2271                                         modules);
2272
2273   g_free (buffer);
2274
2275   return success;
2276 }
2277   
2278 extern GLogLevelFlags logged_levels;
2279
2280 static void
2281 start_element_handler (GMarkupParseContext *context,
2282                        const gchar         *element_name,
2283                        const gchar        **attribute_names,
2284                        const gchar        **attribute_values,
2285                        gpointer             user_data,
2286                        GError             **error)
2287 {
2288   ParseContext *ctx = user_data;
2289   gint line_number, char_number;
2290
2291   if (logged_levels & G_LOG_LEVEL_DEBUG)
2292     {
2293       GString *tags = g_string_new ("");
2294       int i;
2295       for (i = 0; attribute_names[i]; i++)
2296         g_string_append_printf (tags, "%s=\"%s\" ",
2297                                 attribute_names[i],
2298                                 attribute_values[i]);
2299
2300       if (i)
2301         {
2302           g_string_insert_c (tags, 0, ' ');
2303           g_string_truncate (tags, tags->len - 1);
2304         }
2305       g_debug ("<%s%s>", element_name, tags->str);
2306       g_string_free (tags, TRUE);
2307     }
2308
2309   switch (element_name[0]) 
2310     {
2311     case 'a':
2312       if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0) 
2313         {
2314           state_switch (ctx, STATE_ALIAS);
2315           goto out;
2316         }
2317       if (start_type (context, element_name,
2318                       attribute_names, attribute_values,
2319                       ctx, error))
2320         goto out;
2321       break;
2322     case 'b':
2323       if (start_enum (context, element_name, 
2324                       attribute_names, attribute_values,
2325                       ctx, error))
2326         goto out;
2327       break;
2328     case 'c':
2329       if (start_function (context, element_name, 
2330                           attribute_names, attribute_values,
2331                           ctx, error))
2332         goto out;
2333       else if (start_constant (context, element_name,
2334                                attribute_names, attribute_values,
2335                                ctx, error))
2336         goto out;
2337       else if (start_class (context, element_name, 
2338                             attribute_names, attribute_values,
2339                             ctx, error))
2340         goto out;
2341       break;
2342
2343     case 'd':
2344       if (start_discriminator (context, element_name, 
2345                                attribute_names, attribute_values,
2346                                ctx, error))
2347         goto out;
2348       break;
2349
2350     case 'e':
2351       if (start_enum (context, element_name, 
2352                       attribute_names, attribute_values,
2353                       ctx, error))
2354         goto out;
2355       else if (start_errordomain (context, element_name, 
2356                       attribute_names, attribute_values,
2357                       ctx, error))
2358         goto out;
2359       break;
2360
2361     case 'f':
2362       if (start_function (context, element_name, 
2363                           attribute_names, attribute_values,
2364                           ctx, error))
2365         goto out;
2366       else if (start_field (context, element_name, 
2367                             attribute_names, attribute_values,
2368                             ctx, error))
2369         goto out;
2370       break;
2371
2372     case 'g':
2373       if (start_glib_boxed (context, element_name,
2374                             attribute_names, attribute_values,
2375                             ctx, error))
2376         goto out;
2377       else if (start_glib_signal (context, element_name,
2378                              attribute_names, attribute_values,
2379                              ctx, error))
2380         goto out;
2381       break;
2382
2383     case 'i':
2384       if (strcmp (element_name, "include") == 0 &&
2385           ctx->state == STATE_REPOSITORY)
2386         {
2387           const gchar *name;
2388           const gchar *version;
2389
2390           name = find_attribute ("name", attribute_names, attribute_values);
2391           version = find_attribute ("version", attribute_names, attribute_values);
2392
2393           if (name == NULL)
2394             {
2395               MISSING_ATTRIBUTE (context, error, element_name, "name");
2396               break;
2397             }
2398           if (version == NULL)
2399             {
2400               MISSING_ATTRIBUTE (context, error, element_name, "version");
2401               break;
2402             }
2403
2404           if (!parse_include (context, ctx, name, version, error))
2405             break;
2406
2407           ctx->dependencies = g_list_prepend (ctx->dependencies,
2408                                               g_strdup_printf ("%s-%s", name, version));
2409
2410
2411           state_switch (ctx, STATE_INCLUDE);
2412           goto out;
2413         }
2414       if (start_interface (context, element_name, 
2415                            attribute_names, attribute_values,
2416                            ctx, error))
2417         goto out;
2418       else if (start_implements (context, element_name,
2419                                  attribute_names, attribute_values,
2420                                  ctx, error))
2421         goto out;
2422       break;
2423
2424     case 'm':
2425       if (start_function (context, element_name, 
2426                           attribute_names, attribute_values,
2427                           ctx, error))
2428         goto out;
2429       else if (start_member (context, element_name, 
2430                           attribute_names, attribute_values,
2431                           ctx, error))
2432         goto out;
2433       break;
2434
2435     case 'n':
2436       if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_REPOSITORY)
2437         {
2438           const gchar *name, *version, *shared_library;
2439
2440           if (ctx->current_module != NULL)
2441             {
2442               g_set_error (error,
2443                            G_MARKUP_ERROR,
2444                            G_MARKUP_ERROR_INVALID_CONTENT,
2445                            "Only one <namespace/> element is currently allowed per <repository/>");
2446               goto out;
2447             }
2448
2449           name = find_attribute ("name", attribute_names, attribute_values);
2450           version = find_attribute ("version", attribute_names, attribute_values);
2451           shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
2452
2453           if (name == NULL)
2454             MISSING_ATTRIBUTE (context, error, element_name, "name");
2455           else if (version == NULL)
2456             MISSING_ATTRIBUTE (context, error, element_name, "version");
2457           else
2458             {
2459               GList *l;
2460
2461               if (strcmp (name, ctx->namespace) != 0)
2462                 g_set_error (error,
2463                              G_MARKUP_ERROR,
2464                              G_MARKUP_ERROR_INVALID_CONTENT,
2465                              "<namespace/> name element '%s' doesn't match file name '%s'",
2466                              name, ctx->namespace);
2467
2468               ctx->current_module = g_ir_module_new (name, version, shared_library);
2469
2470               ctx->current_module->aliases = ctx->aliases;
2471               ctx->aliases = NULL;
2472               ctx->current_module->disguised_structures = ctx->disguised_structures;
2473               ctx->disguised_structures = NULL;
2474
2475               for (l = ctx->include_modules; l; l = l->next)
2476                 g_ir_module_add_include_module (ctx->current_module, l->data);
2477
2478               g_list_free (ctx->include_modules);
2479               ctx->include_modules = NULL;
2480
2481               ctx->modules = g_list_append (ctx->modules, ctx->current_module);
2482               ctx->current_module->dependencies = ctx->dependencies;
2483
2484               state_switch (ctx, STATE_NAMESPACE);
2485               goto out;
2486             }
2487         }
2488       break;
2489
2490     case 'p':
2491       if (start_property (context, element_name,
2492                           attribute_names, attribute_values,
2493                           ctx, error))
2494         goto out;
2495       else if (strcmp (element_name, "parameters") == 0 &&
2496                ctx->state == STATE_FUNCTION)
2497         {
2498           state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2499
2500           goto out;
2501         }
2502       else if (start_parameter (context, element_name,
2503                                 attribute_names, attribute_values,
2504                                 ctx, error))
2505         goto out;
2506       else if (strcmp (element_name, "prerequisite") == 0 &&
2507                ctx->state == STATE_INTERFACE)
2508         {
2509           const gchar *name;
2510
2511           name = find_attribute ("name", attribute_names, attribute_values);
2512
2513           state_switch (ctx, STATE_PREREQUISITE);
2514
2515           if (name == NULL)
2516             MISSING_ATTRIBUTE (context, error, element_name, "name");
2517           else
2518             {  
2519               GIrNodeInterface *iface;
2520
2521               iface = (GIrNodeInterface *)ctx->current_node;
2522               iface ->prerequisites = g_list_append (iface->prerequisites, g_strdup (name));
2523             }
2524           goto out;
2525         }
2526       break;
2527
2528     case 'r':
2529       if (strcmp (element_name, "repository") == 0 && ctx->state == STATE_START)
2530         {
2531           const gchar *version;
2532
2533           version = find_attribute ("version", attribute_names, attribute_values);
2534           
2535           if (version == NULL)
2536             MISSING_ATTRIBUTE (context, error, element_name, "version");
2537           else if (strcmp (version, "1.0") != 0)
2538             g_set_error (error,
2539                          G_MARKUP_ERROR,
2540                          G_MARKUP_ERROR_INVALID_CONTENT,
2541                          "Unsupported version '%s'",
2542                          version);
2543           else
2544             state_switch (ctx, STATE_REPOSITORY);
2545           
2546           goto out;
2547         }
2548       else if (start_return_value (context, element_name,
2549                                    attribute_names, attribute_values,
2550                                    ctx, error))
2551         goto out;      
2552       else if (start_struct (context, element_name,
2553                              attribute_names, attribute_values,
2554                              ctx, error))
2555         goto out;      
2556       break;
2557
2558     case 'u':
2559       if (start_union (context, element_name,
2560                        attribute_names, attribute_values,
2561                        ctx, error))
2562         goto out;
2563       break;
2564
2565     case 't':
2566       if (start_type (context, element_name,
2567                       attribute_names, attribute_values,
2568                       ctx, error))
2569         goto out;
2570       break;
2571
2572     case 'v':
2573       if (start_vfunc (context, element_name,
2574                        attribute_names, attribute_values,
2575                        ctx, error))
2576         goto out;
2577       if (start_type (context, element_name,
2578                       attribute_names, attribute_values,
2579                       ctx, error))
2580         goto out;
2581       break;
2582     }
2583
2584   g_markup_parse_context_get_position (context, &line_number, &char_number);
2585
2586   if (error && *error == NULL)
2587     g_set_error (error,
2588                  G_MARKUP_ERROR,
2589                  G_MARKUP_ERROR_UNKNOWN_ELEMENT,
2590                  "Unexpected start tag '%s' on line %d char %d; current state=%d",
2591                  element_name,
2592                  line_number, char_number, ctx->state);
2593   
2594  out: ;
2595   if (*error) 
2596     {
2597       g_markup_parse_context_get_position (context, &line_number, &char_number);
2598
2599       fprintf (stderr, "Error at line %d, character %d: %s\n", line_number, char_number, (*error)->message);
2600       backtrace_stderr ();
2601     }
2602 }
2603
2604 static gboolean
2605 require_one_of_end_elements (GMarkupParseContext *context,
2606                              ParseContext        *ctx,
2607                              const char          *actual_name,
2608                              GError             **error, 
2609                              ...)
2610 {
2611   va_list args;
2612   int line_number, char_number;
2613   const char *expected;
2614   gboolean matched = FALSE;
2615
2616   va_start (args, error);
2617
2618   while ((expected = va_arg (args, const char*)) != NULL) 
2619     {
2620       if (strcmp (expected, actual_name) == 0)
2621         {
2622           matched = TRUE;
2623           break;
2624         }
2625     }
2626
2627   va_end (args);
2628
2629   if (matched)
2630     return TRUE;
2631
2632   g_markup_parse_context_get_position (context, &line_number, &char_number);
2633   g_set_error (error,
2634                G_MARKUP_ERROR,
2635                G_MARKUP_ERROR_INVALID_CONTENT,
2636                "Unexpected end tag '%s' on line %d char %d; current state=%d",
2637                actual_name, 
2638                line_number, char_number, ctx->state);
2639   backtrace_stderr();
2640   return FALSE;
2641 }
2642
2643 static gboolean
2644 require_end_element (GMarkupParseContext *context,
2645                      ParseContext        *ctx,
2646                      const char          *expected_name,
2647                      const char          *actual_name,
2648                      GError             **error)
2649 {
2650   return require_one_of_end_elements (context, ctx, actual_name, error, expected_name, NULL);
2651 }
2652
2653 static void
2654 end_element_handler (GMarkupParseContext *context,
2655                      const gchar         *element_name,
2656                      gpointer             user_data,
2657                      GError             **error)
2658 {
2659   ParseContext *ctx = user_data;
2660
2661   g_debug ("</%s>", element_name);
2662
2663   switch (ctx->state)
2664     {
2665     case STATE_START:
2666     case STATE_END:
2667       /* no need to GError here, GMarkup already catches this */
2668       break;
2669
2670     case STATE_REPOSITORY:
2671       state_switch (ctx, STATE_END);
2672       break;
2673
2674     case STATE_INCLUDE:
2675       if (require_end_element (context, ctx, "include", element_name, error))
2676         {
2677           state_switch (ctx, STATE_REPOSITORY);
2678         }
2679       break;
2680
2681     case STATE_NAMESPACE:
2682       if (require_end_element (context, ctx, "namespace", element_name, error))
2683         {
2684           ctx->current_module = NULL;
2685           state_switch (ctx, STATE_REPOSITORY);
2686         }
2687       break;
2688
2689     case STATE_ALIAS:
2690       if (require_end_element (context, ctx, "alias", element_name, error))
2691         {
2692           state_switch (ctx, STATE_NAMESPACE);
2693         }
2694       break;
2695
2696     case STATE_FUNCTION_RETURN:
2697       if (strcmp ("type", element_name) == 0)
2698         break;
2699       if (require_end_element (context, ctx, "return-value", element_name, error))
2700         {
2701           state_switch (ctx, STATE_FUNCTION);
2702         }
2703       break;
2704
2705     case STATE_FUNCTION_PARAMETERS:
2706       if (require_end_element (context, ctx, "parameters", element_name, error))
2707         {
2708           state_switch (ctx, STATE_FUNCTION);
2709         }
2710       break;
2711
2712     case STATE_FUNCTION_PARAMETER:
2713       if (strcmp ("type", element_name) == 0)
2714         break;
2715       if (require_end_element (context, ctx, "parameter", element_name, error))
2716         {
2717           state_switch (ctx, STATE_FUNCTION_PARAMETERS);
2718         }
2719       break;
2720
2721     case STATE_FUNCTION:
2722       {
2723         gboolean current_is_toplevel;
2724         GList *last = g_list_last (ctx->current_module->entries);
2725         
2726         current_is_toplevel = ctx->current_node == last->data;  
2727
2728         if (current_is_toplevel)
2729           {
2730             ctx->current_node = NULL;
2731             state_switch (ctx, STATE_NAMESPACE);
2732           }
2733         else 
2734           { 
2735             ctx->current_node = g_list_last (ctx->current_module->entries)->data;
2736             if (ctx->current_node->type == G_IR_NODE_INTERFACE)
2737               state_switch (ctx, STATE_INTERFACE);
2738             else if (ctx->current_node->type == G_IR_NODE_OBJECT) 
2739               state_switch (ctx, STATE_CLASS);
2740             else if (ctx->current_node->type == G_IR_NODE_BOXED)
2741               state_switch (ctx, STATE_BOXED);
2742             else if (ctx->current_node->type == G_IR_NODE_STRUCT)
2743               state_switch (ctx, STATE_STRUCT);
2744             else if (ctx->current_node->type == G_IR_NODE_UNION)
2745               state_switch (ctx, STATE_UNION);
2746             else
2747               {
2748                 int line_number, char_number;
2749                 g_markup_parse_context_get_position (context, &line_number, &char_number);
2750                 g_set_error (error,
2751                              G_MARKUP_ERROR,
2752                              G_MARKUP_ERROR_INVALID_CONTENT,
2753                              "Unexpected end tag '%s' on line %d char %d",
2754                              element_name,
2755                              line_number, char_number);
2756               }
2757           }
2758       }
2759       break;
2760
2761     case STATE_CLASS_FIELD:
2762       if (strcmp ("type", element_name) == 0)
2763         break;
2764       if (require_end_element (context, ctx, "field", element_name, error))
2765         {
2766           state_switch (ctx, STATE_CLASS);
2767         }
2768       break;
2769
2770     case STATE_CLASS_PROPERTY:
2771       if (strcmp ("type", element_name) == 0)
2772         break;
2773       if (require_end_element (context, ctx, "property", element_name, error))
2774         {
2775           state_switch (ctx, STATE_CLASS);
2776         }
2777       break;
2778
2779     case STATE_CLASS:
2780       if (require_end_element (context, ctx, "class", element_name, error))
2781         {
2782           ctx->current_node = NULL;
2783           state_switch (ctx, STATE_NAMESPACE);
2784         }
2785       break;
2786
2787     case STATE_ERRORDOMAIN:
2788       if (require_end_element (context, ctx, "errordomain", element_name, error))
2789         {
2790           ctx->current_node = NULL;
2791           state_switch (ctx, STATE_NAMESPACE);
2792         }
2793       break;
2794
2795     case STATE_INTERFACE_PROPERTY:
2796       if (strcmp ("type", element_name) == 0)
2797         break;
2798       if (require_end_element (context, ctx, "property", element_name, error))
2799         {
2800           state_switch (ctx, STATE_INTERFACE);
2801         }
2802       break;
2803
2804     case STATE_INTERFACE_FIELD:
2805       if (strcmp ("type", element_name) == 0)
2806         break;
2807       if (require_end_element (context, ctx, "field", element_name, error))
2808         {
2809           state_switch (ctx, STATE_INTERFACE);
2810         }
2811       break;
2812
2813     case STATE_INTERFACE:
2814       if (require_end_element (context, ctx, "interface", element_name, error))
2815         {
2816           ctx->current_node = NULL;
2817           state_switch (ctx, STATE_NAMESPACE);
2818         }
2819       break;
2820
2821     case STATE_ENUM:
2822       if (strcmp ("member", element_name) == 0)
2823         break;
2824       else if (require_one_of_end_elements (context, ctx, 
2825                                             element_name, error, "enumeration", 
2826                                             "bitfield", NULL))
2827         {
2828           ctx->current_node = NULL;
2829           state_switch (ctx, STATE_NAMESPACE);
2830         }
2831       break;
2832
2833     case STATE_BOXED:
2834       if (require_end_element (context, ctx, "glib:boxed", element_name, error))
2835         {
2836           ctx->current_node = NULL;
2837           state_switch (ctx, STATE_NAMESPACE);
2838         }
2839       break;
2840
2841     case STATE_BOXED_FIELD:
2842       if (strcmp ("type", element_name) == 0)
2843         break;
2844       if (require_end_element (context, ctx, "field", element_name, error))
2845         {
2846           state_switch (ctx, STATE_BOXED);
2847         }
2848       break;
2849
2850     case STATE_STRUCT_FIELD:
2851       if (strcmp ("type", element_name) == 0)
2852         break;
2853       if (require_end_element (context, ctx, "field", element_name, error))
2854         {
2855           state_switch (ctx, STATE_STRUCT);
2856         }
2857       break;
2858
2859     case STATE_STRUCT:
2860       if (require_end_element (context, ctx, "record", element_name, error))
2861         {
2862           ctx->current_node = NULL;
2863           state_switch (ctx, STATE_NAMESPACE);
2864         }
2865       break;
2866
2867     case STATE_UNION_FIELD:
2868       if (strcmp ("type", element_name) == 0)
2869         break;
2870       if (require_end_element (context, ctx, "field", element_name, error))
2871         {
2872           state_switch (ctx, STATE_UNION);
2873         }
2874       break;
2875
2876     case STATE_UNION:
2877       if (require_end_element (context, ctx, "union", element_name, error))
2878         {
2879           ctx->current_node = NULL;
2880           state_switch (ctx, STATE_NAMESPACE);
2881         }
2882       break;
2883     case STATE_IMPLEMENTS:
2884       if (strcmp ("interface", element_name) == 0)
2885         break;
2886       if (require_end_element (context, ctx, "implements", element_name, error))
2887         state_switch (ctx, STATE_CLASS);
2888       break;
2889     case STATE_PREREQUISITE:
2890       if (require_end_element (context, ctx, "prerequisite", element_name, error))
2891         state_switch (ctx, STATE_INTERFACE);
2892       break;
2893     case STATE_NAMESPACE_CONSTANT:
2894     case STATE_CLASS_CONSTANT:
2895     case STATE_INTERFACE_CONSTANT:
2896       if (strcmp ("type", element_name) == 0)
2897         break;
2898       if (require_end_element (context, ctx, "constant", element_name, error))
2899         {
2900           ctx->current_node = NULL;
2901           switch (ctx->state)
2902             {
2903             case STATE_NAMESPACE_CONSTANT:
2904               state_switch (ctx, STATE_NAMESPACE);
2905               break;
2906             case STATE_CLASS_CONSTANT:
2907               state_switch (ctx, STATE_CLASS);
2908               break;
2909             case STATE_INTERFACE_CONSTANT:
2910               state_switch (ctx, STATE_INTERFACE);
2911               break;
2912             default:
2913               g_assert_not_reached ();
2914               break;
2915             }
2916         }
2917       break;
2918     case STATE_TYPE:
2919       if ((strcmp ("type", element_name) == 0) || (strcmp ("array", element_name) == 0) ||
2920           (strcmp ("varargs", element_name) == 0))
2921         {
2922           end_type (ctx);
2923           break;
2924         }
2925     default:
2926       g_error ("Unhandled state %d in end_element_handler\n", ctx->state);
2927     }
2928 }
2929
2930 static void 
2931 text_handler (GMarkupParseContext *context,
2932               const gchar         *text,
2933               gsize                text_len,  
2934               gpointer             user_data,
2935               GError             **error)
2936 {
2937   /* FIXME warn about non-whitespace text */
2938 }
2939
2940 static void
2941 cleanup (GMarkupParseContext *context,
2942          GError              *error,
2943          gpointer             user_data)
2944 {
2945   ParseContext *ctx = user_data;
2946   GList *m;
2947
2948   for (m = ctx->modules; m; m = m->next)
2949     g_ir_module_free (m->data);
2950   g_list_free (ctx->modules);
2951   ctx->modules = NULL;
2952   
2953   ctx->current_module = NULL;
2954 }
2955
2956 static GList *
2957 post_filter_varargs_functions (GList *list)
2958 {
2959   GList *iter;
2960
2961   iter = list;
2962   while (iter)
2963     {
2964       GList *link = iter;
2965       GIrNode *node = iter->data;
2966
2967       iter = iter->next;
2968
2969       if (node->type == G_IR_NODE_FUNCTION)
2970         {
2971           if (((GIrNodeFunction*)node)->is_varargs)
2972             {
2973               list = g_list_delete_link (list, link);
2974             }
2975         }
2976     }
2977   return list;
2978 }
2979
2980 static void
2981 post_filter (GIrModule *module)
2982 {
2983   GList *iter;
2984
2985   module->entries = post_filter_varargs_functions (module->entries);
2986   iter = module->entries;
2987   while (iter)
2988     {
2989       GIrNode *node = iter->data;
2990
2991       iter = iter->next;
2992       
2993       if (node->type == G_IR_NODE_OBJECT || 
2994           node->type == G_IR_NODE_INTERFACE) 
2995         {
2996           GIrNodeInterface *iface = (GIrNodeInterface*)node;
2997           iface->members = post_filter_varargs_functions (iface->members);
2998         }
2999       else if (node->type == G_IR_NODE_BOXED)
3000         {
3001           GIrNodeBoxed *boxed = (GIrNodeBoxed*)node;
3002           boxed->members = post_filter_varargs_functions (boxed->members);
3003         }
3004       else if (node->type == G_IR_NODE_STRUCT)
3005         {
3006           GIrNodeStruct *iface = (GIrNodeStruct*)node;
3007           iface->members = post_filter_varargs_functions (iface->members);
3008         }
3009       else if (node->type == G_IR_NODE_UNION)
3010         {
3011           GIrNodeUnion *iface = (GIrNodeUnion*)node;
3012           iface->members = post_filter_varargs_functions (iface->members);
3013         }
3014     }
3015 }
3016
3017 /**
3018  * g_ir_parser_parse_string:
3019  * @parser: a #GIrParser
3020  * @error: return location for a #GError, or %NULL
3021  *
3022  * Parse a string that holds a complete GIR XML file, and return a list of a
3023  * a #GirModule for each &lt;namespace/&gt; element within the file.
3024  *
3025  * @returns: a newly allocated list of #GIrModule. The modules themselves
3026  *  are owned by the #GIrParser and will be freed along with the parser.
3027  */
3028 GList *
3029 g_ir_parser_parse_string (GIrParser           *parser,
3030                           const gchar         *namespace,
3031                           const gchar         *buffer,
3032                           gssize               length,
3033                           GError             **error)
3034 {
3035   ParseContext ctx = { 0 };
3036   GMarkupParseContext *context;
3037
3038   ctx.parser = parser;
3039   ctx.state = STATE_START;
3040   ctx.namespace = namespace;
3041   ctx.include_modules = NULL;
3042   ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
3043   ctx.disguised_structures = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
3044   ctx.type_depth = 0;
3045   ctx.dependencies = NULL;
3046   ctx.current_module = NULL;
3047
3048   context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL);
3049
3050   if (!g_markup_parse_context_parse (context, buffer, length, error))
3051     goto out;
3052
3053   if (!g_markup_parse_context_end_parse (context, error))
3054     goto out;
3055
3056   g_markup_parse_context_free (context);
3057   
3058   context = g_markup_parse_context_new (&markup_parser, 0, &ctx, NULL);
3059   if (!g_markup_parse_context_parse (context, buffer, length, error))
3060     goto out;
3061
3062   if (!g_markup_parse_context_end_parse (context, error))
3063     goto out;
3064
3065   parser->parsed_modules = g_list_concat (g_list_copy (ctx.modules),
3066                                           parser->parsed_modules);
3067
3068  out:
3069
3070   if (ctx.modules == NULL)
3071     {
3072       /* An error occurred before we created a module, so we haven't
3073        * transferred ownership of these hash tables to the module.
3074        */
3075       if (ctx.aliases != NULL)
3076         g_hash_table_destroy (ctx.aliases);
3077       if (ctx.disguised_structures != NULL)
3078         g_hash_table_destroy (ctx.disguised_structures);
3079       g_list_free (ctx.include_modules);
3080     }
3081   
3082   g_markup_parse_context_free (context);
3083   
3084   return ctx.modules;
3085 }
3086
3087 /**
3088  * g_ir_parser_parse_file:
3089  * @parser: a #GIrParser
3090  * @error: return location for a #GError, or %NULL
3091  *
3092  * Parse GIR XML file, and return a list of a a #GirModule for each
3093  * &lt;namespace/&gt; element within the file.
3094  *
3095  * @returns: a newly allocated list of #GIrModule. The modules themselves
3096  *  are owned by the #GIrParser and will be freed along with the parser.
3097  */
3098 GList *
3099 g_ir_parser_parse_file (GIrParser   *parser,
3100                         const gchar *filename,
3101                         GError     **error)
3102 {
3103   gchar *buffer;
3104   gsize length;
3105   GList *modules;
3106   GList *iter;
3107   const char *slash;
3108   char *dash;
3109   char *namespace;
3110
3111   if (!g_str_has_suffix (filename, ".gir"))
3112     {
3113       g_set_error (error,
3114                    G_MARKUP_ERROR,
3115                    G_MARKUP_ERROR_INVALID_CONTENT,
3116                    "Expected filename to end with '.gir'");
3117       return NULL;
3118     }
3119
3120   g_debug ("[parsing] filename %s", filename);
3121
3122   slash = g_strrstr (filename, "/");
3123   if (!slash)
3124     namespace = g_strdup (filename);
3125   else
3126     namespace = g_strdup (slash+1);
3127   namespace[strlen(namespace)-4] = '\0';
3128
3129   /* Remove version */
3130   dash = strstr (namespace, "-");
3131   if (dash != NULL)
3132     *dash = '\0';
3133
3134   if (!g_file_get_contents (filename, &buffer, &length, error))
3135     return NULL;
3136   
3137   modules = g_ir_parser_parse_string (parser, namespace, buffer, length, error);
3138
3139   for (iter = modules; iter; iter = iter->next) 
3140     {
3141       post_filter ((GIrModule*)iter->data);
3142     }
3143
3144   g_free (namespace);
3145
3146   g_free (buffer);
3147
3148   return modules;
3149 }
3150
3151