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