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