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