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