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