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