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