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