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