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